|
Ko sem med učenjem asemblerja naletel na naslednjo kodo, sem preprosto pomislil, da program ne more normalno končati. Vendar pa so po enostopenjskem sledenju z odpravljanjem napak ugotovili, da se program lahko normalno zaključi, in zgodil se je nenavaden pojav: ko se je program začel izvajati iz code:0005 na code:0014, je z ukazom jmp nadaljeval s preskakovanjem na code:0008. Vendar pa, ko nadaljujemo s korakom naprej, program preskoči neposredno na code:0 namesto code:0018 (tj. označevalni segment S1). Sprva nisem razumel, kaj se dogaja, a po številnih opazovanjih v enem koraku sem se še vedno počutil čudno. Po natančnem preučevanju uporabe JMP ukazov v učbeniku [1] in nato analizi programa v kombinaciji s strojno kodo sem pridobil novo razumevanje JMP ukazov. strojna navodila za sestavljanje kode z naslovnim zamikom (IP) Predpostavimo CS:Code (Unit: H) Kodni 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 Koda se konča konec začetka 1. Naslednji dve točki je treba jasno razumeti 1. Postopek izvajanja ukazov CPU je naslednji: <1>. Preberi ukaz iz pomnilniške enote, na katero kaže CS:IP, in ga vstavi v medpomnilnik ukazov. <2>. IP=IP+Dolžina ukaza, ki se trenutno bere v medpomnilnik, torej IP kaže na naslednji ukaz. <3>. Izvedite trenutni ukaz v medpomnilniku. Pojdi na korak <1> 2. Pomen kratkega ukaza jmp za prenos notranjega segmenta <1>. IP je odmik, torej naslov pri označevalcu IP = - naslov prvega bajta po ukazu jmp. <2>. Funkcija tega ukaza je spremeniti vrednost IP, in po izvedbi ukaza je IP = IP + 8-bitni zamik < 3> in 8 bitov imata razpon premika -128~127, premik pa je izražen v obliki komplementa [2]. 2. Analiza kode 1. Korak 1: Program se začne izvajati od vhodnega začetka (code:0005), ko se izvede ukaz code:0013~0014, strojna koda stavka jmp, kratka S1 na oznaki S2, se kopira v code:0008, IP pa je 0016. V tem trenutku, ob predpostavki, da ni ukaza jmp short s, se program izvede na s2:jmp short s1, prebere jmp short s1 v medpomnilnik ukazov in IP=0022; prenos iz s2 v s1 je prenos znotraj segmenta, format strojne kode je EB disp, disp = oznaka s1-oznaka s2=(00018-0022) complement=F6, tako da mora biti strojna koda ukaza jmp short s1 EBF6. Zato se EBF6 kopira v enoto code:0008~code:0009. 2. Korak 2: Preberi ukaz jmp short s (EBF0) v medpomnilnik ukazov, IP=IP+0002=0018; dopolnilna koda oznake s-oznaka s0=(0008-0018) = F0, prenos iz s0 v s je prenos znotraj segmenta, strojna koda pa je EB disp (tj. EBF0) 3. Korak 3: Ukaz jmp short s(EBF0) je ukaz za spremembo IP-ja, po izvedbi ukaza EBF0, IP=IP+(oznaka s-oznaka s0)=0008, ki kaže na enoto kod:0008. 4. Korak 4: Preberi vsebino kode enote: 0008. Ker se ukaz jmp short s1 (EBF6) na s2 kopira v enoto code:0008~code:0009, po branju vsebine enote je IP=IP+0002=000A 5. Korak 5: Ukaz jmp short s1 (EBF6) je ukaz za spremembo IP, po izvedbi ukaza EBF6, IP=IP+(oznaka s1-oznaka s2)=0000, ki kaže na enoto code:0000. 6. Korak 6: Program gre na kod:0000 za izvajanje, torej je običajni konec zaključen. 3. P.S. Pravilno analizirajte to kodo: Morate razumeti postopek izvajanja ukazov CPU in jmp kratkega jezika? (izračunano z modifikacijo IP). Poleg tega je ključna tudi komplementna koda rezultata izračuna zamika. Po analizi te na videz nenavadne kode sem pridobil globlje razumevanje JMP ukazov v asemblerju.
|