匯編入門(mén)學(xué)習筆記 (八)—— 轉移指令
參考: 《匯編語(yǔ)言》 王爽 第9章
可以修改ip或者同時(shí)修改cs和ip的指令統稱(chēng)為轉移指令。
8086CPU轉移行為分為:
段內轉移:只修改ip
段間轉移:同時(shí)修改cs和ip
段內轉移按ip修改的范圍可分為:
短轉移:ip修改范圍 -128~127
近轉移:ip修改范圍 -32768~32767
轉移指令分為:
無(wú)條件轉移指令。如 jmp
條件轉移指令
循環(huán)指令。如 loop
過(guò)程。
中斷。
1. offset,nop指令
offset 獲取標號的偏移地址
nop 占用1一個(gè)字節
例子:
- assumecs:code
- codesegment
- start:movax,bx
- movsi,offsetstart
- movdi,offsets
- movax,cs:[si]
- movcs:[di],ax
- s:nop
- nop
- codeends
- endstart
2. 依據位移進(jìn)行轉移的jmp指令
(1)jmp short 標號
是段內短轉移。
表示轉移到指定的標號處,且轉移的距離范圍為-128~127
用debug查看此指令時(shí),會(huì )看見(jiàn)機器碼,不會(huì )保存標號的地址,自會(huì )保存轉移的距離
(2)jmp near ptr標號
是段內近轉移,轉移的距離范圍為-32768~32767,其他與jmp short 標號相同
2. 轉移地址在寄存器中的jmp指令
jmp 16位 reg
表示 (IP)=(16位 reg)
3.轉移地址在內存中的jmp指令
(1)jmp word ptr 內存單元地址
是段內近轉移。
例子:轉移到偏移地址為0123H的指令去,即使(IP)= 0123H
- movax,0123H
- movds:[0],ax
- jmpwordptrds:[0]
(2)jmp dword ptr 內存單元地址
是段間轉移
高地址表示轉移的段地址
低地址表示偏移地址
用debug查看機器碼,可以發(fā)現,它是保存了段地址與偏移地址,而不是像段內轉移的指令時(shí)保存轉移的距離
例子:轉移到段地址為0,偏移地址為0123H的指令去,即使得(CS)= 0,(IP)= 0123H
- movax,0123H
- movds:[0],ax
- movwordptrds:[2],0
- jmpdwordptrds:[0]
4. jcxz 指令
jcxz 指令為條件轉移指令。當cx為0時(shí),轉移(與loop剛剛相反)。所有條件轉移指令都是短轉移。
例子:在內存2000H段中查找第一個(gè)值位0 的字節,并把它的偏移指定存儲在dx中。
- assumecs:code
- codesegment
- start:movax,2000H
- movds,ax
- movbx,0
- s:movch,0
- movcl,[bx]
- jcxzok
- incbx
- jmpshorts
- ok:movdx,bx
- movax,4c00H
- int21H
- codeends
- endstart
5. jmp指令詳細分析
向前轉移:jmp s
jmp short s
jmp near ptr s
jmp far ptr s
在像前轉移時(shí),編譯器可以在讀到標號s后記下AC(地址計算器)的值as,在讀到j(luò )mp ...s (上面5種)后記下AC的值aj。編譯器可以用as-aj計算出disp
(1)如果disp 在-128~127 內
上面的每一種指令都將轉化為jmp short s
(2)如果disp 在-32768~32767內
對于jmp short s會(huì )編譯錯誤
對于jmp s,jmp near ptr s會(huì )產(chǎn)生jmp near ptr s所對應的機器碼。
對于jmp far ptr s,所對應的機器碼為:EA 偏移地址 段地址。
先后轉移:
由于不能確定s位置,編譯器先將上面的指令都當做 jmp short s來(lái)讀取。記下jmp ..s 指令的位置和AC的值aj。
對于jmp short s 編譯器生成一個(gè)EB和一個(gè)nop指令
對于jmp near ptr s編譯器生成一個(gè)EB和兩個(gè)nop指令
對于jmp far ptr s編譯器生成一個(gè)EB和四個(gè)nop指令
當讀到s時(shí),記下AC的值as,計算disp = as - aj
(1)如果disp 在-128~127 內
指令都為 EB disp ,它們后面的一個(gè)nop變成8位的disp 。jmp s(1個(gè))、jmp near ptr s (1個(gè))跟jmp far ptr s (3個(gè)) nop指令不變
(2)如果disp 在-32768~32767內
對于jmp short s會(huì )編譯錯誤
jmp s、jmp near ptr s 后面 兩個(gè)nop變成轉移的16位disp。
jmp far ptr s 這填上相應的段地址,偏移地址。
6. 分析一個(gè)奇怪的程序
- assumecs:code
- codesegment
- movax,4c00h
- int21h
- start:movax,0
- s:nop
- nop
- movdi,offsets
- movsi,offsets2
- movax,cs:[si]
- movcs:[di],ax
- s0:jmpshorts
- s1:movax,0
- int21h
- movax,0
- s2:jmpshorts1
- nop
- codeends
- endstart
追后程序會(huì )運行s處的
mov ax,4c00h
int 21h
而正常終止。
為什么?
debug可以發(fā)現,jmp short s1 復制到s處后,由原來(lái)的jmp 0018H變成 jmp 0000H。
但是本質(zhì)的機器碼是EBF6沒(méi)變就是ip = ip - 10。
評論