1. 程式人生 > >組合語言入門:CALL和RET的配合使用(一)

組合語言入門:CALL和RET的配合使用(一)

本系列教程完全參照王爽《組合語言(第三版)》,這本書對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中