|
Quando mi sono imbattuto nel seguente codice mentre imparavo il linguaggio assembly, ho semplicemente pensato che il programma non potesse finire normalmente. Tuttavia, dopo il debug single-step tracking, si scoprì che il programma poteva terminare normalmente, e si verificò un fenomeno strano: quando il programma iniziava a eseguire dal codice :0005 al codice 0014, continuava a saltare al codice 0008 con il comando jmp. Tuttavia, continuando a eseguire un passo avanti, il programma salta direttamente al code:0 invece che al code:0018 (cioè al segmento designatore S1). All'inizio non capivo cosa stesse succedendo, ma dopo molte osservazioni a un solo passo, mi sentivo comunque strano. Dopo aver studiato attentamente l'uso delle istruzioni JMP nel libro di testo [1], e poi aver analizzato il programma in combinazione con il codice macchina, ho acquisito una nuova comprensione delle istruzioni JMP. Istruzioni macchine offset di codice assemblaggio (IP) Assumiamo CS:Code (Unità: H) Segmento di codice mov ax, 4C00H 0000 B8004C int 21h 0003 CD21 start: mov ax,0 0005 B80000 S: NOP 0008 90 NOP 0009 90 mov di, offset s 000A BF0800 mov si, offset s2 000D BE2000 mov ax,cs:[si] CS:0020=F6EB mov cs:[di],ax CS:0008=9090 s0: jmp short s 0016 EBF0 s1: mov ax, 0 0018 B80000 int 21h 001B CD21 mov ax, 0 001D B80000 s2: jmp short s1 0020 EBF6 NOP 0022 90 Fine del codice fine inizio 1. I seguenti due punti devono essere compresi chiaramente 1. Il processo di esecuzione delle istruzioni CPU è il seguente: <1>. Leggi l'istruzione dall'unità di memoria indicata da CS:IP e mettila nel buffer delle istruzioni. <2>. IP=IP+La lunghezza dell'istruzione attualmente letta nel buffer, cioè l'IP punta all'istruzione successiva. <3>. Esegui il comando corrente nel buffer. Vai al passo <1> 2. Il significato del comando breve jmp per trasferire il segmento interno <1>. IP è lo spostamento, cioè l'indirizzo al designatore IP = - l'indirizzo del primo byte dopo il comando jmp. <2>. La funzione di questo comando è modificare il valore di IP e, dopo l'esecuzione del comando, IP = IP + offset di 8 bit < bit 3> e 8 hanno un intervallo di spostamento di -128~127, e lo spostamento è espresso sotto forma di complemento [2]. 2. Analisi del codice 1. Passo 1: Il programma inizia a eseguire dall'inizio dell'ingresso (code:0005), quando viene eseguita la dichiarazione code:0013~0014, il codice macchina dell'istruzione jmp short S1 sull'etichetta S2 viene copiato in code:0008, e l'IP è 0016. In questo momento, assumendo che non ci sia un'istruzione jmp short s, il programma verrà eseguito su s2:jmp short s1, leggerà jmp short s1 nel buffer delle istruzioni e IP=0022; e il trasferimento da s2 a s1 è il trasferimento intra-segmento, il formato del codice macchina è EB disp, e disp=designazione s1-designazione s2=(00018-0022) complement=F6, quindi il codice macchina del comando jmp short s1 dovrebbe essere EBF6. Pertanto, EBF6 viene copiato nell'unità code:0008~code:0009. 2. Passo 2: Leggi l'istruzione jmp short s (EBF0) nel buffer delle istruzioni, IP=IP+0002=0018; il codice di complemento della designazione s-designazione s0=(0008-0018) = F0, e il trasferimento da s0 a s è il trasferimento intra-segmento, e il formato del codice macchina è EB disp (cioè EBF0) 3. Passo 3: Il comando jmp short s(EBF0) è un comando per modificare l'IP, dopo aver eseguito il comando EBF0, IP=IP+(designazione s-designazione s0)=0008, puntando al code:0008 unit. 4. Passo 4: Leggi il contenuto del codice unità:0008. Poiché il comando jmp short s1 (EBF6) a s2 viene copiato nell'unità code:0008~code:0009, dopo aver letto il contenuto dell'unità, IP=IP+0002=000A 5. Passo 5: Instruction jmp short s1 (EBF6) è un comando per modificare IP, dopo aver eseguito il comando EBF6, IP=IP+(designazione s1-designazione s2)=0000, puntando al codice:0000 unità. 6. Passo 6: Il programma va a code:0000 per eseguire, cioè la fine normale è completata. 3. Postfacium Analizza correttamente questo codice: bisogna capire il processo di esecuzione delle istruzioni CPU e jmp short? (calcolato tramite modifica IP). Inoltre, il codice di complemento del risultato del calcolo dell'offset è anch'esso un elemento chiave. Dopo aver analizzato questo codice apparentemente anomalo, ho acquisito una comprensione più profonda delle istruzioni JMP nell'assembly.
|