iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0

前幾天有提到,在 Linux x86-64 中,Function 的 Argument 通常會放在:

RDI
RSI
RDX
RCX
R8
R9

而 Return Value 通常會放在:

RAX

也有看過很多次:

ret

但一個 Function 到底是怎麼被呼叫的?

今天就來看看 Assembly 裡面的:

call
ret

0x01 Function Call

先看一段簡單的 C Code:

int add(int a, int b) {
    return a + b;
}

int main() {
    return add(10, 20);
}

Compile 之後,可能會看到類似:

main:
    mov esi, 20
    mov edi, 10
    call add

前面有提過:

RDI → 第一個 Argument
RSI → 第二個 Argument

所以可以理解成:

mov edi, 10
mov esi, 20 
等價成
add(10, 20);

接著:

call add

就是呼叫:

add

這個 Function。


0x02 call

那:

call add

到底做了什麼?

可以先簡單理解成兩件事情:

1. 記住等等要回來的位置
2. 跳到 add Function

例如:

call add
mov ebx, eax

CPU 執行:

call add

之後會跳到:

add:

開始執行。

但是 add 執行完之後,還需要知道要回來繼續執行:

mov ebx, eax

所以 call 會先保存一個:

Return Address

也就是:

Function 執行完之後,要回到哪裡繼續執行。

這個 Return Address 會被放到:

Stack

Stack 的部分下一篇再詳細介紹。


0x03 ret

有了 Return Address 之後,Function 執行完就可以使用:

ret

回到原本的位置。

例如:

add:
    lea eax, [rdi+rsi]
    ret

流程可以簡單想成:

main
 |
 | call add
 v
add
 |
 | 計算結果
 |
 | ret
 v
main 繼續執行

所以:

call

負責進入 Function。

而:

ret

負責回到原本呼叫 Function 的地方。


0x04 Return Value

前面也有提到:

RAX → Return Value

例如:

add:
    lea eax, [rdi+rsi]
    ret

假設:

RDI = 10
RSI = 20

那:

lea eax, [rdi+rsi]

可以先理解成:

EAX = 10 + 20

所以最後:

EAX = 30

而 EAX / RAX 通常就是 Function 的 Return Value。

因此這段:

add:
    lea eax, [rdi+rsi]
    ret

就可以理解成:

return a + b;

0x05 Calling Convention

Function Argument 放在哪個 Register、Return Value 放在哪裡,並不是隨便決定的。

這些規則通常會由:

Calling Convention

來定義。

在 Linux x86-64 常見的 System V AMD64 Calling Convention 中:

RDI → Argument 1
RSI → Argument 2
RDX → Argument 3
RCX → Argument 4
R8  → Argument 5
R9  → Argument 6

RAX → Return Value

例如:

test(1, 2, 3);

可以先想成:

RDI = 1
RSI = 2
RDX = 3

接著:

call test

Function 裡面就可以從這些 Register 取得 Argument。

不過不同 Architecture、Operating System 或 Calling Convention,規則可能不一樣。

目前先記住 Linux x86-64 這組就可以了。


0x06 一個完整 Function Call

再看一次:

int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(10, 20);
    return result;
}

可以先把 Assembly 簡化理解成:

main:
    mov esi, 20
    mov edi, 10
    call add
    ret

add:
    lea eax, [rdi+rsi]
    ret

整個流程就是:

10 → EDI
20 → ESI
    |
    v
 call add
    |
    v
EDI + ESI
    |
    v
   EAX
    |
    v
   ret

所以當看到:

call function_name

可以先想:

準備 Argument
    ↓
進入 Function
    ↓
Function 執行
    ↓
結果放進 RAX
    ↓
ret 回去

0x07 結論

今天可以先記得:

call

他是會:

保存 Return Address
+
跳到指定 Function

而:

ret

則會:

回到 Return Address

另外在 Linux x86-64 中:

RDI → Argument 1
RSI → Argument 2
RDX → Argument 3
RCX → Argument 4
R8  → Argument 5
R9  → Argument 6

RAX → Return Value

現在已經可以大概看懂一個 Function 是怎麼被呼叫的。

但前面提到:

Return Address

會被放到:

Stack

那 Stack 到底是什麼?

RSP、RBP 又是在做什麼?

Function 裡面的 Local Variable 又放在哪裡?

下一篇就來看看:Stack


上一篇
Day05|Assembly - 2
下一篇
Day07|Stack
系列文
從零開始の Binary CTF:30 天系統化學習 Rev & Pwn 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言