|
När jag stötte på följande kod medan jag lärde mig assembler, trodde jag helt enkelt att programmet inte kunde sluta normalt. Efter felsökning av enkelstegsspårning upptäcktes dock att programmet kunde avsluta normalt, och ett märkligt fenomen uppstod: när programmet började köras från kod:0005 till kod:0014 fortsatte det att hoppa till kod:0008 med kommandot jmp. Men när man fortsätter att utföra ett steg framåt hoppar programmet direkt till kod:0 istället för kod:0018 (dvs. segmentet för beteckningen S1). Till en början förstod jag inte vad som pågick, men efter många enskilda observationer kände jag mig ändå konstig. Efter att noggrant ha studerat användningen av JMP-instruktioner i läroboken [1], och sedan analyserat programmet i kombination med maskinkod, har jag fått en ny förståelse för JMP-instruktioner. assemble code address offset (IP) maskininstruktioner Antag CS:Code (enhet: H) Kodsegment 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 Koden slutar slutstart 1. Följande två punkter måste förstås tydligt 1. Processen för CPU-instruktionsexekvering är som följer: <1>. Läs instruktionen från minnesenheten som CS:IP pekar på och lägg den i instruktionsbufferten. <2>. IP=IP+Längden på instruktionen som för närvarande läses in i bufferten, det vill säga IP-adressen pekar på nästa instruktion. <3>. Utför det aktuella kommandot i bufferten. Gå till steg <1> 2. Betydelsen av jmp-kortkommandot för att överföra det interna segmentet <1>. IP är offseten, det vill säga adressen vid IP = designatorn – adressen till den första byten efter jmp-kommandot. <2>. Funktionen för detta kommando är att ändra värdet på IP, och efter att kommandot har utförts, IP = IP + 8-bitars offset < 3> och 8 bitar har ett förskjutningsområde på -128~127, och offsetet uttrycks i form av komplement [2]. 2. Kodanalys 1. Steg 1: Programmet börjar köras från ingångsstarten (kod:0005), när kod:0013~0014-satsen körs kopieras maskinkoden för satsen jmp short S1 vid etiketten S2 till kod:0008, och IP-adressen är 0016. Vid denna tidpunkt, förutsatt att det inte finns någon jmp short s-instruktion, kommer programmet att köras till s2:jmp short s1, läsa jmp short s1 in i instruktionsbufferten och IP=0022; och överföringen från s2 till s1 är intrasegmentöverföringen, maskinkodformatet är EB disp, och disp=beteckning s1-beteckning s2=(00018-0022) complement=F6, så maskinkoden för kommandot jmp short s1 bör vara EBF6. Därför kopieras EBF6 till kod:0008~kod:0009-enheten. 2. Steg 2: Läs in instruktionen jmp short s (EBF0) i instruktionsbufferten, IP=IP+0002=0018; komplementkoden för beteckningen s0=(0008-0018) = F0, och överföringen från s0 till s är intrasegmentöverföringen, och maskinkodformatet är EB disp (dvs. EBF0) 3. Steg 3: Kommandot jmp short s(EBF0) är ett kommando för att ändra IP, efter att kommandot EBF0 har utförts, IP=IP+(beteckning s-beteckning s0)=0008, vilket pekar på kod:0008-enheten. 4. Steg 4: Läs innehållet i enhetskod:0008. Eftersom kommandot jmp short s1 (EBF6) vid s2 kopieras till kod:0008~kod:0009-enheten, efter att ha läst innehållet i enheten, IP=IP+0002=000A 5. Steg 5: Instruktion jmp short s1 (EBF6) är ett kommando för att ändra IP, efter att kommandot EBF6 har utförts, IP=IP+(beteckning s1-beteckning s2)=0000, vilket pekar på kod:0000-enheten. 6. Steg 6: Programmet går till kod:0000 för att köra, det vill säga att det normala slutet slutförs. 3. Efterord Korrekt analysera denna kod: Behöver du förstå processen för CPU-instruktionsexekvering och JMP-kortslutning? (beräknat genom IP-modifiering). Dessutom är komplementkoden för offset-beräkningsresultatet också en nyckel. Efter att ha analyserat denna till synes onormala kod fick jag en djupare förståelse för JMP-instruktionerna i assembleren.
|