可以修改IP,或者同時修改cs和ip的指令統稱為轉移指令。
8086cpu的轉移行為有以下幾類:
- 只修改ip,稱為段內轉移,如
jmp ax
- 同時修改cs和ip,稱為段間轉移,如
jmp 1000:0
根據轉移指令對於ip的修改范圍不同,所以段內轉移又分為:短轉移和近轉移
- 短轉移IP的修改返回為-128~127
- 近轉移IP的修改范圍為-32768~32767
8086cpu的轉移指令分為以下幾類:
- 無條件轉移指令(如:jmp)
- 條件轉移指令 (jcxz)
- 循環指令(loop)
- 過程
- 中斷
不同轉移指令的轉移條件可能不同,但是轉移的基本原理是相同的
操作符offset
offset是在匯編語言中是由編譯器處理的符號,功能為取得標號的偏移地址。也就是相對於代碼段的偏移地址,就是直接IP值了。
jmp指令
jmp為無條件轉移指令,可以只修改IP,也可以同時修改cs和ip。
jmp指令需要給出兩種信息:
- 轉移的目的地址
- 轉移的距離(段間轉移,段內短轉移,段內近轉移)
不同的給出目的地址的方法不同,和不同的轉移位置,對應有不同格式的jmp指令。
依據位移進行轉移的jmp指令
jmp short 標號
(IP)=(IP)+8位位移
這種格式的jmp指令實現的是段內短轉移。對ip的修改范圍限定為-128~127之間,可以看出正好是一個字節能夠表示的范圍。jmp near ptr 標號
(IP)=(IP)+16位位移
於jmp short
功能相同,只不過他實現的是段內近轉移。簡單來說就是轉移的距離拉長(雖然仍然是在段內)
小貼士:
可以看到jmp short
與jmp near ptr
(段內轉移)並沒有直接將轉移的目的地址直接寫入機器指令中。而是將一個相對偏移地址寫入了機器指令。(但是debug在對應的匯編指令中會看到偏移地址)
具體來說就是將標號地址相對於jmp指令的下一條指令的地址寫入了機器指令。
也就是說,cpu在執行jmp指令的時候並不需要轉移的目標地址。
轉移的目的地址在指令中的jmp指令
前面講到的段內轉移指令其機器指令中並沒有轉移的目的地址,而是相對於當前ip的轉移位移。
jmp far ptr 標號
實現段間轉移,又稱為遠轉移。
(CS)=標號所在段的段地址;(IP)=標號在段中的偏移地址
far ptr
將標號的地址寫入了匯編指令。
jmp指令的機器碼為EA,可以很明顯的看出來,其中高地址放段地址,低地址放偏移地址。
順便說明,像是jmp 1000:0
是在debug中使用的,在匯編代碼中並不能使用這樣的指令。
轉移地址在寄存器中的jmp指令
指令格式: jmp 16位reg
功能: (IP)=(16位reg)
轉移地址在內存中的jmp指令
轉移地址在內存中的jmp指令有兩種格式:
jmp word ptr 內存單元地址
(段內轉移)
更改ip值。jmp dword ptr 內存單元地址
(段間轉移)
目標內存中放着兩個字,其中高地址處的字為轉移目標的段地址,低地址處的字為轉移的目標的段偏移地址。
(CS)=(內存單元地址+2)
(IP)=(內存單元地址)
jcxz指令
jcxz
為條件轉移指令。所有的條件轉移指令都是短轉移指令,在對應的機器碼中包含轉移的位移,而不是目的地址。對IP的修改范圍為-128~127.
功能:當cx寄存器的值為0是執行轉移,否則什么也不做。
loop指令
loop指令為循環指令,所有的循環指令都是短轉移。
根據位移進行轉移的意義
高端大氣的說法就是方便了程序段在內存中的浮動裝配。
實際上就是無所謂程序在內存中的地址,程序中的轉移指令無需改變。
編譯器對於轉移位移超界的檢測
根據位移進行轉移的指令,他們的轉移范圍收到轉移位移的限制,如果在源程序中出現了轉移范圍超界的問題,在編譯的時候,編譯器將會報錯。
分析一個奇怪的程序
就是一個計算通過相對偏移位置計算偏移位置的問題。
會注意到在執行完mov cs:[di], ax
以后,s段的9090
(nop nop)變成了EBF6
(值為F6EB【小端序】)。同時想到的是同樣都是EBF6
卻翻譯出了不同的匯編指令。然而實際上都是相同的,翻譯的問題是編譯器做的。他將機器碼翻譯了以下,也就是將相對偏移地址直接翻譯成為了IP中的偏移地址。
即使上面講到過的偏移地址=jmp的下一條指令地址+相對偏移地址(注意到F6的問題,計算機中的數據以補碼方式存儲)。他就是將偏移地址算了出來。
根據材料編程
答案:
assume cs:code, ds:data
data segment
db 'welcome to masm!' ; 文字
db 00000010B, 00100100B, 01110001B ; 屬性
data ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, 0b800H
mov es, ax
mov bx, 0
mov si, 0
mov di, 64
mov bp, 6e0H
mov cx, 3
ln:
mov dx, cx
mov cx, 16
mov bx, 0
mov di, 64
s:
mov al, [bx]
mov ah, 16[si]
mov es:[bp].[di], ax
inc bx
add di, 2
loop s
add si, 1
add bp, 160
mov cx, dx
loop ln
mov ax, 4c00H
int 21H
code ends
end start
注意數值不能以字母開頭