|
Keď som narazil na nasledujúci kód počas učenia assemblera, jednoducho som si myslel, že program nemôže skončiť normálne. Po jednokrokovom sledovaní debugu sa však zistilo, že program môže skončiť normálne, a nastal zvláštny jav: keď program začal vykonávať z code:0005 na code:0014, pokračoval v skoku na code:0008 pomocou príkazu jmp. Avšak pri pokračovaní v kroku vpred program preskočí priamo na kód:0 namiesto kód:0018 (t. j. označovací segment S1). Najprv som nechápal, čo sa deje, ale po mnohých jednorazových pozorovaniach som sa stále cítil zvláštne. Po dôkladnom štúdiu použitia JMP inštrukcií v učebnici [1] a následnej analýze programu v kombinácii so strojovým kódom získavam nové chápanie JMP inštrukcií. Strojové inštrukcie na zostavenie kódu a posunu adresy (IP) Predpokladajme cs:code (jednotka: h) Kódový segment 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 Kód končí koniec štartu 1. Nasledujúce dva body je potrebné jasne pochopiť 1. Proces vykonávania inštrukcií CPU je nasledovný: <1>. Prečítať inštrukciu z pamäťovej jednotky, na ktorú ukazovalo CS:IP, a vložiť ju do inštrukčného bufferu. <2>. IP=IP+Dĺžka inštrukcie, ktorá sa práve číta do vyrovnávacej pamäte, teda IP smeruje na ďalšiu inštrukciu. <3>. Vykonajte aktuálny príkaz v bufferi. Prejdite na krok <1> 2. Význam krátkeho príkazu jmp na prenos vnútorného segmentu <1>. IP je offset, teda adresa na označovači IP = – adresa prvého bajtu po príkaze jmp. <2>. Funkciou tohto príkazu je upraviť hodnotu IP a po vykonaní príkazu je IP = IP + 8-bitový offset < 3> a 8 bitov majú rozsah posunu -128~127 a posun sa vyjadruje vo forme doplnku [2]. 2. Analýza kódu 1. Krok 1: Program začne vykonávať od vstupného štartu (code:0005), keď sa vykoná príkaz code:0013~0014, strojový kód príkazu jmp short S1 na štítku S2 sa skopíruje na code:0008 a IP je 0016. V tomto momente, za predpokladu, že neexistuje inštrukcia jmp short s, program sa spustí na s2:jmp short s1, načíta jmp short s1 do inštrukčného bufferu a IP=0022; a prenos zo s2 do s1 je prenos v rámci segmentu, strojový kód je EB disp a disp=označenie s1-označenie s2=(00018-0022) complement=F6, takže strojový kód príkazu jmp short s1 by mal byť EBF6. Preto sa EBF6 skopíruje do jednotky kód:0008~code:0009. 2. Krok 2: Prečítajte inštrukciu jmp short s (EBF0) do inštrukčného bufferu, IP=IP+0002=0018; doplnkový kód označenia s-označenia s0=(0008-0018) = F0, a prenos zo s0 do s je prenos v rámci segmentu, pričom formát strojového kódu je EB disp (t. j. EBF0) 3. Krok 3: Príkaz jmp short s(EBF0) je príkaz na úpravu IP po vykonaní príkazu EBF0, IP=IP+(označenie s-označenie s0)=0008, ktorý ukazuje na jednotku kód:0008. 4. Krok 4: Prečítajte si obsah kódu jednotky:0008. Keďže príkaz jmp short s1 (EBF6) v s2 je skopírovaný do jednotky kód:0008~code:0009, po načítaní obsahu jednotky je IP=IP+0002=000A 5. Krok 5: Inštrukcia jmp short s1 (EBF6) je príkaz na úpravu IP po vykonaní príkazu EBF6, IP=IP+(označenie s1-označenie s2)=0000, ktorý ukazuje na jednotku kód:0000. 6. Krok 6: Program prejde na code:0000 na vykonanie, teda normálny koniec je dokončený. 3. Dodatok Správne analyzovať tento kód: Potrebujete pochopiť proces vykonávania inštrukcií CPU a jmp short? (vypočítané úpravou IP). Okrem toho je kľúčovým aj doplnkový kód výsledku výpočtu offsetu. Po analýze tohto zdanlivo abnormálneho kódu som získal hlbšie pochopenie JMP inštrukcií v assembleri.
|