汇编学习笔记(二):转移指令
章節目錄
作者能力有限, 如果您在閱讀過程中發現任何錯誤, 還請您務必聯系本人,指出錯誤, 避免后來讀者再學習錯誤的知識.謝謝!
本文中所有程序均在DOSBox下使用MASM, LINK編譯運行
轉移指令原理
轉移指令是可以控制 CPU 執行內存中某處代碼的指令. 而 CPU 執行內存中哪處的指令是由 CS 和 IP 寄存器中的決定的. 因此, 轉移指令是通過修改 CS 和 IP 寄存器的值來控制 CPU 對指令的執行的.
只修改 IP 的轉移行為稱為 段內轉移.
同時修改 CS 和 IP 的轉移行為稱為 段間轉移.
由于轉移指令對 IP 的修改范圍不同, 段內轉移又分為: 短轉移和近轉移.
短轉移: 對 IP 修改范圍為 -128 ~ 127.
近轉移: 對 IP 修改范圍為 -32768 ~ 32767.
jmp 指令
jmp為無條件轉移指令, 可以修改 IP 或者同時修改 CS 和 IP.
jmp short 標號
這條指令完成段內短轉移. 對 IP 的修改范圍為:-128 ~ 127. 執行完該指令之后, CS 的值不變, IP 指向標號在段中的偏移地址.
示例:
在上面程序中我們通過 jmp short s 將 IP 指向標號 s 的偏移地址. 當程序執行到 jmp 時, 會直接跳轉到 s 處, 從 s 處繼續往下執行.
jmp far ptr 標號
這條指令完成段間轉移, 又稱為遠轉移. 執行完該指令之后, CS 指向標號所在的段基址, IP 指向標號在段中的偏移地址.
示例:
在上面程序中我們通過 jmp far ptr s 將 CS 指向標號 s 的段基址, IP 指向標號 s 的偏移地址. 當程序執行到 jmp 時, 會直接跳轉到 s 處, 從 s 處繼續往下執行.
其他 jmp 指令
當然轉移地址可以存儲在寄存器或者內存中, 相應的語法如下:
jmp reg // 其中 reg 為 16位寄存器,其中存儲這要跳轉的偏移地址.
jmp word ptr 內存單元地址 // 段內轉移, 內存單元存放目的偏移地址.
// 示例:
mov ax, 0123H
mov ds:[0], ax
jmp word ptr [ds]:[0] // IP = 0123H
jmp dword ptr 內存單元地址 // 段間轉移, 內存單元兩個字節,
//高地址處存放著轉移的目的段基址, 低字節存放的是轉移的目的偏移地址.
// 示例:
mov ax, 0123H
mov ds:[0], ax
mov word ptr ds:[2], 0
jmp word ptr [ds]:[0] // CS = 0, IP = 0123H
Note: 轉移指令,不僅僅可以向后跳轉, 亦可以向前跳轉.
jcxz 指令
該指令為有條件轉移指令. 所有有條件轉移指令都是短轉移.
指令格式: jcxz 標號(如果 CX = 0, 轉移到標號處執行)
jcxz 的功能相當于: if (CX == 0) jmp short 標號
當 CX != 0 時, jcxz 什么也不做, 程序繼續向下執行.
示例:
loop 指令
該指令在上一篇文章中已經涉及,示例可參考匯編語言筆記(一)
ret 和 retf 指令
ret 指令用棧中的數據, 修改 IP 的值, 實現近轉移.
retf 指令用棧中的數據, 修改 CS 和 IP 的值, 實現遠轉移.
CPU 執行 ret 指令時, 進行如下兩步操作:
IP = SS * 16 + SP
SP = SP + 2
相當于: pop IP
CPU 執行 retf 執行時, 進行如下四步操作:
IP = SS * 16 + SP
SP = SP + 2
CS = SS * 16 + SP
SP = SP + 2
相當于:
pop IP
pop CS
示例:
ret 用法
retf 用法:
上述程序中, ret/retf 執行執行后, IP = 0, CS:IP 指向代碼段的第一條指令.
call 指令
CPU 執行 call 指令時, 執行以下兩步操作:
將當前的 IP 或者 CS 和 IP 壓入棧中
轉移
call 指令不能實現短轉移.
call 標號
CPU 執行此指令時, 執行如下操作:
(1) SP = SP - 2, SS * 16 + SP = IP
(2) IP = IP + 16 位位移
執行 call 標號 指令相當于執行:
push IP
jmp near ptr 標號
call far ptr 標號
CPU 執行此指令時, 執行如下操作:
(1) SP = SP - 2, SS * 16 + SP = CS
SP = SP - 2, SS * 16 + SP = IP
(2) CS = 標號所在段的段基址
IP = 標號在段中的偏移地址
執行 call far ptr 標號 指令相當于執行:
push CS
push IP
jmp far ptr 標號
其他 call 指令
當然轉移地址可以存儲在寄存器或者內存中, 相應的語法如下:
call reg
reg 為16位寄存器
相應 CPU 操作:
SP = SP - 2, SS * 16 + SP = IP
IP = reg 中的值
相當于:
push IP
jmp reg
call word ptr 內存單元地址
相當于:
push IP
jmp word ptr 內存單元地址
示例:
mov sp, 10H
mov ax, 0123H
mov ds:[0], ax
call word ptr ds:[0] // 執行后 IP = 0123H, SP=0EH
call dword ptr 內存單元地址
相當于:
push CS
push IP
jmp dword ptr 內存單元地址
示例:
mov sp, 10H
mov ax, 0123H
mov ds:[0], ax
mov word ptr ds:[2], 0
call word ptr ds:[0] // 執行后 CS=0, IP = 0123H, SP=0CH
call + ret
建議在繼續往下看之前, 仔細閱讀一下上圖中代碼, 分析程序結束時 bx 中的值是多少?
分析一下這個程序將非常有助于我們理解 call 和 ret 指令.
(1) 程序執行到 call s 時, IP 此時指向了 call s 的下一條指令 mov bx, ax (CS 和 IP 指向了 CPU 當前要讀取指令的地址. 而當前已經執行到了 call s,因此下一條要讀取的指令將是 mov bx, ax);
(2) CPU 執行 call s 時, 將當前 IP 值(指向 mov bx, ax 的偏移地址)壓棧, 并將 IP 的值改變為標號 s 的偏移地址.
(3) CPU 從標號 s 處開始執行指令, loop 循環結束后, ax = 8
(4) CPU 將 ret 指令讀入, IP 指向了 ret 指令后的內存單元(此時僅僅是讀取指令,還未執行 ret 指令);
(5) CPU 執行 ret 指令, 從棧中彈出一個值(即 call s 指令先前壓入的 mov bx, ax 指向的偏移地址), 將該值存入 IP 中. 此時 CS:IP 指向指令 mov bx, ax.
(6) 執行完 ret 指令之后, 程序將跳轉到 mov bx, ax 處繼續執行, 直至完成.
(7) 最終, bx = 8.
歡迎交流任何想法.
End…
1
總結
以上是生活随笔為你收集整理的汇编学习笔记(二):转移指令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 唯一约束 多字段_mysql
- 下一篇: 2020,再见;2021,我来了!