組合語言入門:CALL和RET的配合使用(一)
阿新 • • 發佈:2019-02-16
本系列教程完全參照王爽《組合語言(第三版)》,這本書對call、ret指令做了相當一部分的講解,其重要性可見一斑
從棧的角度分析call和ret
分析以下程式碼
assume cs:code
stack segment
db 8 dup (0) 1000:0008 00 00 00 00 00 00 00 00
db 8 dup (0) 1000:0000 00 00 00 00 00 00 00 00
stack ends
code segment
start:mov ax,stack 1001:0000 B8 00 10
mov ss,ax 1001:0003 8E 00
mov sp,16 1001:0005 BC 10 00
mov ax,1000 1001:0008 B8 E8 03
call s 1001:000B E8 05 00
mov ax,4c00h 1001:000E B8 00 4C
int 21h 1001:0013 03 C0
s:add ax,ax 1001:0013 03 C0
ret 1001:0015 C3
code ends
end start
分析(從start程式碼段開始看)
1. 初始化棧CS、IP指標(dup表示重複,共16個0),讓SS=1000,SP=16
2. 讓(ax) = 1000
前三條指令執行後,如圖所示
3. 呼叫子程式,push下一行的首地址(push 000E,call預設進行near轉移)
4. 進入子程式s(CPU從cs:0013H開始執行)
5. ret指令讀入,IP首先自增1(這個不重要),CPU接著執行C3處的程式碼,相當於pop IP,執行後,棧中的情況為
6. CPU回到cs:000EH處繼續執行
call和ret的配合使用,與高階語言的關係
call指令
push ip
jmp 標號 ; 預設near轉移
ret指令(near轉移)
pop ip
retf指令(far轉移)
pop ip
pop cs
高階語言的程式返回
void foo()
{
printf("foo");
return;
}
高階語言的return
語句通常相當於組合語言的retf
(遠轉移)
mul指令
mul
指令用來做乘法,它只能進行8位/8位或16位/16位的乘法
如果是8位/16位乘法,要先將8位用16位資料進行儲存(高位補0)
根據參與乘法的兩個數的位數,結果儲存在ax或ax和dx中