第9章 轉移指令的原理
一、8086轉移指令的分類
1、無條件轉移指令,如jmp;
2、條件轉移指令,如jcxz;
3、循環指令,如loop;
4、過程;
5、中斷
二、幾種轉移指令的詳解
*基礎知識:補碼
在計算機系統中,數值一律用補碼來表示(存儲)。正數補碼與原碼相同,如十進制17;原碼為0001 0001;其補碼也為0001 0001;
負數的補碼最高位取1,剩余7位為將負數取絕對值按位取反后+1,得其補碼(對8位補碼)。如-1;最高位取1,絕對值7位為0000001,按位取反后為1111110;+1后為1111111;則-1的補碼為11111111.
也可知,對8位補碼,其可表示的數值范圍為-128~127;對16位補碼其表示范圍為-32768~32767.
*offset操作符:offset 標號 表示:獲取標號位置處的偏移地址。
1、段內短轉移:jmp short 標號
其僅對ip值進行修改;修改范圍是-128~127(往前128個字節,往后127個字節);
在機器碼中,jmp short 標號對應的是使用位移來尋址,該語句告訴CPU的並不是目的地址,而是基於當前ip的位移量。
如下指令及設其ip對應如下:
mov ax,0--------IP:a1
mov bx,0--------IP:a1+3
jmp short s--------IP:a1+6
add ax,1--------IP:b1
s:add ax,2--------IP:b2
當ip=a1+6時候,CPU讀取jmp short s進入指令緩沖區;ip指向下一條指令,即ip=b1;然后執行jmp short s;執行完畢后指令指向標號s處,即ip=b2;其位移量為(b2-b1);通過上述分析可知,位移量應為(目標偏移地址減去jmp指令下一條指令的偏移地址)。
也因此,jmp short s的功能為:(IP)=(IP)+8位位移量(位移量的計算是在編譯過程中計算出的)。以上例具體來說位移量為b2-b1.而執行完jmp指令后的ip=b1;即新的(ip)=b2-b1+b1=b2。
2、段內近轉移:jmp near ptr 標號;
其功能與段內短轉移類似,表達為:(IP)=(IP)+16位位移量
3、不使用位移量轉移而直接指定轉移目的地址的jmp指令
(1)轉移目的地址在指令中的jmp指令
段間轉移(遠轉移):jmp far ptr 標號
表達為:(CS)=標號所在段的段地址;(IP)=標號所在位置的偏移地址。
(2)轉移地址在寄存器中的jmp指令:jmp 16位reg
表達為:(IP)=(16位reg)
(3)轉移地址在內存中的jmp指令:jmp word/dword ptr 內存單元地址
如:jmp word ptr ds:[0]
功能為:CS不變,(IP)=(ds:[0])
如:jmp dword ptr ds:[0]
功能為:(CS)=(ds:[2]),(IP)=(ds:[0])
4、條件轉移指令:jcxz 標號
表達為:if((cx)==0) jmp short 標號
注意:所有的條件轉移均為短轉移。即位移量為-128~127.
5、循環指令loop 標號
表達為:
cx=cx-1;
if ((cx)!=0) jmp short 標號
注意:所有的循環轉移也均為短轉移。即位移量為-128~127.
三、通過位移量確定轉移地址的幾個指令
總共有4類,jmp型的有兩種:
(1)jmp short 標號
(2)jmp near ptr 標號
另外等價的還有兩種:
(3)jcxz 標號:等價於 if(!(cx)) jmp short 標號
(4)loop 標號:等價於:先(cx)=(cx)-1;再if((cx)) jmp short標號
檢測點9.1
(1)要使程序中jmp指令執行后,cs:ip指向程序第一條指令,data段該如何定義。
分析:jmp word ptr []使用的是直接給出偏移地址,即這里ds:[bx+1]的值要為0.
對於data段來說,就是第二個內存單元值為0,對其他無所謂。
assume cs:code data segment db 0,0 data ends code segment start:mov ax,data mov ds,ax mov bx,0 jmp word ptr [bx+1] code ends
(2)補全程序,使得jmp執行后,cs:ip指向程序第一條指令。
分析:jmp dword ptr ds:[0]設置的是(cs)=(ds:[2]);(ip)=(ds:[0])。
assume cs:code data segment dd 12345678H data ends code segment start: mov ax, data mov ds, ax mov bx, 0 mov [bx],bx mov [bx+2], cs jmp word ptr ds:[0] mov ax, 4c00h int 21h code ends end start
檢測點9.2
補全程序,利用jcxz指令,在內存2000H段中查找第一個為0的單元,將其偏移地址存儲在dx中。
assume cs:code code segment start:mov ax,2000h mov ds,ax mov bx,0 s: mov cl,ds:[bx]; mov ch,0; jcxz ok; inc bx; jmp short s ok: mov dx,bx mov ax ,4c00h int 21h code ends end start
檢測點9.3
補全程序,利用loop指令,實現在內存2000H段中查找第一個為0的單元,將其偏移地址存儲在dx中。
assume cs:code code segment start: mov ax,2000H mov ds,ax mov bx,0 s: mov cl,[bx] mov ch,0 inc cx ;自增1滿足loop跳出條件 inc bx loop s ok: dec bx mov dx,bx mov ax,4c00h int 21h code ends end start
實驗8 分析一個奇怪的程序
assume cs:codesg codesg segment mov ax,4c00h ;A int 21h ;B start mov ax,0 s: nop ;C nop ;D mov di,offset s ;E mov si,offset s2 mov ax,cs:[si] mov cs:[di],ax ;把s2處的jmp short s1代碼復制到s處,而該jmp代碼實質是偏移-(x+2)個字節單位。 s0: jmp short s s1: mov ax,0 int 21h mov ax,0 ;設s1開始的這三句占據x字節 s2: jmp short s1 ;這句jmp本身占據2字節,則此處實質偏移量為-(x+2) nop codesg ends end start ;先從start入口開始執行,到F處執行完成后就是使得s標號處的代碼變成了jmp指令 ;繼續往下執行到s0標號處,執行完跳轉到標號s處 ;此時s處的代碼已經更新為jmp指令,該指令實質為往前偏移(x+2)個單元。 ;可以看出A到E中間的代碼長度和s1到s2處的nop的長度是一樣的。所以執行s處的代碼后,跳轉到A處 ;執行A,B;退出程序返回