|
Když jsem při učení assembleru narazil na následující kód, prostě jsem si myslel, že program nemůže normálně skončit. Po jednokrokovém sledování debugu se však zjistilo, že program může normálně skončit, a došlo k podivnému jevu: když program začal spouštět z code:0005 na code:0014, pokračoval ve skoku na code:0008 pomocí příkazu jmp. Při pokračování v kroku vpřed však program přeskočí přímo na kód:0 místo kód:0018 (tj. označovací segment S1). Nejdřív jsem nechápal, co se děje, ale i po mnoha jednokrokových pozorováních jsem se stále cítil divně. Po pečlivém studiu použití JMP instrukcí v učebnici [1] a následné analýze programu v kombinaci se strojovým kódem získávám nové pochopení JMP instrukcí. strojové instrukce pro assembler code address offset (IP) Předpokládejme 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: JPP Short S1 0020 EBF6 nop 0022 90 Kód končí konec startu 1. Následující dva body je třeba jasně pochopit 1. Proces provádění instrukcí CPU je následující: <1>. Přečíst instrukci z paměťové jednotky ukazované CS:IP a vložit ji do instrukční bufferu. <2>. IP=IP+Délka instrukce, která je právě čtena do bufferu, tedy IP ukazuje na další instrukci. <3>. Spusť aktuální příkaz v bufferu. Přejděte na krok <1> 2. Význam krátkého příkazu jmp pro přenos vnitřního segmentu <1>. IP je offset, tedy adresa u označovače IP = – adresa prvního bajtu po příkazu jmp. <2>. Funkcí tohoto příkazu je upravit hodnotu IP a po jeho spuštění je IP = IP + 8bitový posun < bity 3> a 8 mají rozsah posunutí -128~127 a posun je vyjádřen ve formě doplňku [2]. 2. Analýza kódu 1. Krok 1: Program začíná spouštět od vstupního startu (code:0005), kdy je vykonán příkaz code:0013~0014, strojový kód příkazu jmp short S1 na štítku S2 je zkopírován do code:0008 a IP adresa je 0016. V tuto situaci, za předpokladu, že neexistuje instrukce jmp short s, program se spustí na s2:jmp short s1, načte jmp short s1 do instrukčního bufferu a IP=0022; a přenos ze s2 do s1 je intra-segmentový přenos, strojový kód je EB disp a disp=označení s1-označení s2=(00018-0022) complement=F6, takže strojový kód příkazu jmp short s1 by měl být EBF6. Proto je EBF6 zkopírován do jednotky kód:0008~code:0009. 2. Krok 2: Přečtěte instrukci jmp short s (EBF0) do instrukčního bufferu, IP=IP+0002=0018; doplňkový kód označení s-označení s0=(0008-0018) = F0 a přenos ze s0 do s je intra-segmentový přenos, a formát strojového kódu je EB disp (tj. EBF0) 3. Krok 3: Příkaz jmp short s(EBF0) je příkaz k úpravě IP po provedení příkazu EBF0, IP=IP+(označení s-designation s0)=0008, který ukazuje na jednotku kód:0008. 4. Krok 4: Přečtěte obsah kódu jednotky:0008. Protože příkaz jmp short s1 (EBF6) v s2 je zkopírován do jednotky kód:0008~code:0009, po přečtení obsahu jednotky je IP=IP+0002=000A 5. Krok 5: Instrukce jmp short s1 (EBF6) je příkaz pro úpravu IP po provedení příkazu EBF6, IP=IP+(označení s1-označení s2)=0000, který ukazuje na jednotku kód:0000. 6. Krok 6: Program přejde na code:0000 k vykonání, tedy je dokončen normální konec. 3. Dodatek Správně analyzujte tento kód: Potřebujete pochopit proces provádění instrukcí CPU a jmp short? (vypočítáno úpravou IP). Kromě toho je klíčovým doplňkovým kódem výsledku výpočtu offsetu. Po analýze tohoto zdánlivě abnormálního kódu jsem získal hlubší porozumění JMP instrukcím v assembleru.
|