- 什么是轉移指令:
可以修改IP,或同時修改CS和IP的指令統稱為轉移指令。轉移指令可以通過修改CS和IP的值來實現對CPU執行內存某處代碼的控制
-
段內轉移:指令轉移方式
IP=IP+位移。等同於JMP 當前IP+需要位移字節段內轉移只修改IP,還是處於一個CS段地址內,例如:JMP AX
-
段內短轉移:
JMP SHORT 標號段內短轉移,位移為8bit位,最高位為符號位。剩余7個bit位可位移,位移間距是:
-128~127,也就是說在編譯之后,使用JMP SHORT 標號指令往前轉移最多128個字節,往后轉移最多127個字節。代碼示例:
ASSUME CS:CODE CODE SEGMENT START: MOV AX,0 MOV BX,0 JMP SHORT S ADD AX,1 ; 機器碼:B80100 ADD AX,3 ; 機器碼:B80300 DB 121 DUP(0) S: INC AX CODE ENDS END START編譯后的機器碼為121個00字節的機器碼。121+3(B80100)+3(B80300)=127個字節,如果將DB 121 DUP(0)改成DB 122 DUP(0),那么程序在MASM 編譯時期就無法通過,因為129個字節已經完全超過了8位bit。不信的話可以試試
-
段內近轉移:
JMP NEAR PTR 標號段內近轉移,位移為16個bit位,最高位為符號bit位,剩余15個bit為可進行位移,位移間距是
-32768~32767,在編譯之后,使用JMP NEAR PTR 標號轉移指令至多往前轉移32768個字節,往后至多轉移32767字節。代碼示例:
ASSUME CS:CODE CODE SEGMENT START: MOV AX,0 MOV BX,0 JMP NEAR PTR S ADD AX,2 DB 128 DUP(0) S: INC AX CODE ENDS END STARTJMP NEAR PTR 標號編譯后的機器碼為E90000。后面四位就是位移范圍,低位在前,高位在后。用法與JMP SHORT基本一致,只不過前者適用於需要更大幅度的單元跳轉的場景 -
為啥近轉移比短轉移多了個
PTR關鍵字?這是網上搜索到的一句話:
匯編里面 ptr 是規定 的 字 (既保留字),是用來臨時指定類型的
-
-
段間轉移:
JMP FAR PTR 標號段間轉移,同時修改CS和IP的值,可跨越不同段直接進行指令轉移。等同於
JMP CS:IP。同時CS=標號所在段地址,IP=標號所在段地址偏移量。也就是說最大轉移幅度應該是(cs*10H)+IP=FFFFF。相當於20個bit位進行位移。最大幅度應該是-1,048,576~1,048,575個字節。 -
使用內存單元進行指令轉移
-
使用內存單元進行近轉移:
JMP WORD PTR 內存單元地址從內存單元地址處開始存放着一個字,是轉移目的地指令的偏移地址。
偏移地址計算方式:JMP DS:[BX]。將BX指向的內存單元中的數據用於IP寄存器的值。跳轉到指定的位置。偏移量范圍參考:
段內近轉移 -
使用內存單元進行段間轉移:
JMP DWORD PTR 內存單元地址
-
-
有條件轉移
所有有條件轉移指令都是短轉移,在對應的機器碼中包含轉移的位移,而不是目的地址。對IP的修改范圍參考段內短轉移-
JCXZ 指令
JCXZ 標號為有條件轉移指令之一,它用於判斷CX是否等於0,如果等於0,則執行指令轉移,否則它什么都不做,程序繼續往下執行,用Java語言的語法表示為:if(cx == 0){jmp ip}。這樣舉例或許更好理解JCXZ指令的作用代碼示例:
ASSUME CS:CODE,DS:DATA CODE SEGMENT START: MOV AX,DATA MOV DS,AX MOV AX,0 MOV BX,0 S: MOV CL,DS:[BX] ; 將內存單元中的值取出,保存到CL中 JCXZ SAVE ; 如果CX==0時,轉移到SAVA標號處,保存當前BX的偏移量 INC BX ; 如果CX!=0時,BX+1,也就是偏移量+1。繼續轉移到S標號處執行 JMP SHORT S SAVE: MOV DX,BX MOV AH,4CH INT 21H CODE ENDS DATA SEGMENT DB 12,20,32,00,36 DATA ENDS END START -
LOOP 指令
LOOP 標號是一個循環指令,但是也是屬於有條件轉移指令的一種。需要注意的是所有循環指令都是短轉移。它判斷CX中的值,是否需要進行指令轉移。跟JCXZ指令恰恰相反,LOOP指令用判斷CX-1之后是否不等於0,如果不等於0則轉移到標號處。如果等於0,則程序往下執行。用Java語言表示的話,應該是下面代碼所執行的效果,其中while就相當於LOOP指令,每次指令LOOP指令轉移時,先將CX中的值-1,然后在判斷CX不等於0Assembly代碼:
ASSUME CS:CODE CODE SEGMENT MOV CX,32 S: ; LOOP循環體代碼段,這里只能有125個字節哦 LOOP S COED ENDSJava代碼:
public class Test{ public static void main(String[] args){ int cx = 32; while((--c) != 0){ // 標號處到LOOP指令之間的代碼段 } } }
以上舉的兩個例子都是使用CX寄存器是否為0進行條件判斷的。還有使用標志寄存器作為條件進行指令轉移的指令,詳情查看:《條件轉移指令之使用標志寄存器進行指令轉移》
-
