第九章
可以修改IP或者同時修改CS和IP的指令統稱爲轉移指令
只修改IP的爲段內轉移,如:jmp ax
同時修改CS和IP的爲段間轉移,如:jmp 1000:0
段內轉移又分爲:短轉移和近轉移
短轉移IP的修改範圍爲-128~127
近轉IP的修改範圍爲-32768~32767
8086轉移指令分類
· 無條件轉移指令(如:jmp)
· 條件轉移指令
· 循環指令(如:loop)
· 過程
· 中斷
9.1 操作符offset
offset在彙編語言中是由編譯器處理的符號,功能是取得標號的偏移地址
assume cs:codesg
codesg segment
start: mov ax,offset start ; 相當於mov ax,0
s: mov ax,offset s ; 相當於mov ax,3
codesg ends
end start
有如下程序段,將該程序中s處的一條指令複製到s0處
assume cs:codesg
codesg segment
s: mov ax,bx ; 機器碼佔兩個字節
mov si,offset s
mov di,offset s0
mov ax,cs:[si]
mov cs:[di],ax
s0: nop
nop ; nop的機器碼佔兩個字節
codesg ends
end s
9.2 jmp指令
jmp指令要給出兩種信息
1、轉移的目的地址
2、轉移的距離
不同的方法有不同的jmp格式
9.3 依據位移進行轉移的jmp指令
jmp short 標號(轉到標號處執行指令)
這種格式實現段內短轉移,對IP的修改範圍爲-128~127
如下程序,ax只進行了一次加1操作
assume cs:codesg
codesg segment
start: mov ax,0
jmp short s
add ax,1
s: inc ax
codesg ends
end start
一般的彙編指令中,立即數都會在對應的機器指令中出現,但是將上述代碼翻譯成機器語言,發現 jmp short s對應的機器碼爲EB03,修改程序
assume cs:codesg
codesg segment
start: mov ax,0
mov bx,0
jmp short s
add ax,1
s: inc ax
codesg ends
end start
修改後s的偏移地址與之前的位置不同,但 jmp short s對應的機器碼仍然爲EB03,結論是CPU在執行jmp指令的時候並不需要轉移的目的地址,至於爲什麼是EB 03,因爲當前地址爲CS:0008H,目標地址爲CS:000BH,所以將IP值加3就是目標指令,因爲這兩個程序jmp指令轉移的位移相同,所以都爲EB 03
因此 jmp short 標號指令所對應的機器碼中,並不包含轉移的目的地址,而包含轉移的位移,是編譯器根據彙編指令中的標號計算出來的
注意計算位移的方法,因爲讀取了jmp指令後,IP會指向下一條指令,所以位移是下一條指令地址與目標指令地址的差
該位移爲8位,補碼錶示(所以範圍爲-128~127)
對應的 jmp near ptr實現段內近轉移
位移爲16位(範圍-32768~32767)
9.4 轉移的目的地址在指令中的jmp指令
jmp far ptr 標號實現段間轉移,又稱爲遠轉移
far ptr指明瞭用標號的段地址和偏移地址修改CS和IP
(CS)=標號所在段的段地址 (IP)=標號在段中的偏移地址
9.5 轉移地址在寄存器中的jmp指令
格式 jmp 16位reg
(IP)=(16位reg)
9.6 轉移地址在內存中的jmp指令
jmp word ptr 內存單元地址(段內轉移)
某內存單元地址處存放着一個字,是轉移的目的偏移地址
內存單元地址可用尋址方式的任一格式給出
jmp word ptr ds:[0]
jmp word ptr [bx]
jmp dword ptr 內存單元地址(段間轉移)
某內存單元地址處存放着兩個字,高地址處的字是轉移的目的段地址,低地址處是轉移的目的偏移地址
(CS)=(內存單元+2)
(IP)=(內存單元地址)
mov ax,0123H
mov ds:[0],ax
mov word ptr ds:[2],0 ; 指明長度
jmp dword ptr ds:[0]
執行後{CS}=0 (IP)=0123H
補全程序,使jmp指令執行後,CS:IP指向程序的第一條指令
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],word ptr 0或mov [bx],offset start
mov [bx+2],cs ; mov [bx+2],code
jmp dword ptr ds:[0]
code ends
end start
9.7 jcxz指令
jcxz指令爲有條件轉移指令,所有的有條件轉移指令都是短轉移,在對應的機器碼中包含轉移的位移,對IP的修改範圍是-128~127
格式:jcxz 標號(如果(cx)=0,轉移到標號處執行)
當(cx) != 0,什麼也不做,程序向下執行
功能等價於 if ((cx) == 0) jmp short 標號;
補全編程,利用jczx指令,實現在內存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
jcxz ok
inc bx
jmp short s
ok: mov dx,bx
mov ax,4c00h
int 21h
code ends
end start
9.8 loop指令
所有的循環指令都是短轉移,對應的機器碼中包含轉移的位移,對IP的修改範圍是-128~127
指令格式 loop 標號((cx)=(cx)=1,如果(cx) != 0,轉移到標號處執行)
等價於
(cx)–
if ((cx) != 0) jmp short 標號;
補全編程,利用jczx指令,實現在內存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 ; loop s處cx也會減一,因此如果cx爲0,loop執行後
inc bx ; cx爲-1,不能正常退出循環,因此先再加1
loop s
ok: dec bx ; dec效果與inc相反,自減
mov dx,bx
mov ax,4c00h
int 21h
code ends
end start
9.9 根據位移進行轉移的意義
方便程序段在內存中的浮動裝配,如
mov cx,6
mov ax,10h
s: add ax,ax
loop s
這段程序在內存的不同位置都可正確執行,無論s處的指令的實際地址是多少,loop指令的轉移位移是不變的
9.10 編譯器對轉移位移超界的檢測
assume cs:code
code segment
start: jmp short s
db 128 dup (0)
s: mov ax,0ffffh
code ends
end start
jmp short s的轉移範圍是-128~127,IP最多向後移動127個字節
在Debug中使用的指令如"jmp 2000:0100"的轉移指令,編譯時會報錯,不能在源程序中使用