|
Kun törmäsin seuraavaan koodiin opetellessani assembler-kieltä, ajattelin vain, ettei ohjelma voisi päättyä normaalisti. Kuitenkin virheenkorjauksen yksivaiheisen seurannan jälkeen havaittiin, että ohjelma saattoi päättyä normaalisti, ja tapahtui outo ilmiö: kun ohjelma alkoi suorittaa code:0005:stä code:0014:ään, se jatkoi hyppimistä code:0008:aan jmp-komennolla. Kuitenkin, kun ohjelma jatkaa askeleen eteenpäin, se hyppää suoraan code:0::an sijaan code:0018:aan (eli tunnisteen S1-segmenttiin). Aluksi en ymmärtänyt, mitä tapahtui, mutta monien yksittäisten havaintojen jälkeen tunsin silti oloni oudoksi. Tutkittuani huolellisesti JMP-käskyjen käyttöä oppikirjassa [1] ja analysoituani ohjelman yhdessä konekoodin kanssa, sain uuden ymmärryksen JMP-käskyistä. assemble code address offset (IP) -konekäskyt Oletetaan cs:code (yksikkö: h) koodisegmentti 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 koodi päättyy loppu alku 1. Seuraavat kaksi seikkaa on ymmärrettävä selkeästi 1. Suorittimen käskyjen suoritusprosessi on seuraava: <1>. Lue käsky CS:IP:n osoittamasta muistiyksiköstä ja laita se käskypuskuriin. <2>. IP=IP+Puskuriin luettavan käskyn pituus, eli IP osoittaa seuraavaan käskyyn. <3>. Suorita nykyinen komento puskurissa. Mene vaiheeseen <1> 2. Jmp-lyhyen komennon merkitys sisäisen segmentin siirtämiseksi <1>. IP on offset, eli osoite IP = -osoitteessa – ensimmäisen tavun osoite jmp-komennon jälkeen. <2>. Tämän komennon tehtävänä on muuttaa IP-arvoa, ja komento suoritettuaan IP = IP + 8 bittiä siirtymää < 3> ja 8 bittiä ovat siirtymäalueella -128~127, ja siirtymä ilmaistaan komplementtina [2]. 2. Koodianalyysi 1. Vaihe 1: Ohjelma alkaa suorittaa sisääntulon alusta (code:0005), kun code:0013~0014-lause suoritetaan, konekoodi lauseesta jmp short S1 tunnisteessa S2 kopioidaan code:0008, ja IP-osoite on 0016. Tällä hetkellä, olettaen ettei ole jmp short s -käskyä, ohjelma suoritetaan s2:jmp short s1, lukee jmp short s1 käskypuskuriin ja IP=0022; ja siirto s2:sta s1:een on segmentin sisäinen siirto, konekoodimuoto on EB disp, ja disp=nimitys s1-merkintä s2=(00018-0022) complement=F6, joten komennon jmp short s1 konekoodi tulisi olla EBF6. Tästä syystä EBF6 kopioidaan koodiin: 0008~koodi:0009. 2. Vaihe 2: Lue käsky jmp short s (EBF0) käskypuskuriin, IP=IP+0002=0018; s-merkinnän komplementtikoodi s0=(0008-0018) = F0, ja siirto s0:sta s:ään on segmentin sisäinen siirto, ja konekoodin muoto on EB disp (eli EBF0) 3. Vaihe 3: Komento jmp short s(EBF0) on komento, jolla IP-osoitetta muokataan komento EBF0, IP=IP+(nimitys s-designation s0)=0008, osoittaen koodi:0008 yksikköä. 4. Vaihe 4: Lue yksikkökoodin sisältö: 0008. Koska komento jmp short s1 (EBF6) kohdassa s2 kopioidaan koodiin: 0008~code:0009, yksikön sisällön lukemisen jälkeen IP=IP+0002=000A 5. Vaihe 5: Käsky jmp short s1 (EBF6) on komento IP:n muokkaamiseen komento EBF6, IP=IP+(nimitys s1-merkintä s2)=0000 jälkeen, osoittaen koodi:0000-yksikköä. 6. Vaihe 6: Ohjelma siirtyy code:0000:een suorittaakseen, eli normaali loppu on suoritettu. 3. Jälkikirjoitus Analysoi tämä koodi oikein: Tarvitsetko ymmärtää CPU:n käskyjen suoritusprosessin ja jmp-oikotuksen prosessin? (laskettu IP-muokkauksella). Lisäksi offset-laskennan tuloksen komplementtikoodi on myös avainasema. Analysoituani tätä näennäisesti epänormaalia koodia sain syvemmän ymmärryksen JMP-käskyistä kokoonpanossa.
|