C 函式呼叫過程

2021-09-12 14:56:24 字數 2349 閱讀 3489

int fun1(int a, int b)

int main()

將彙編**執行到函式呼叫的地方,檢視函式呼叫引數帶入的指令。

int a = fun1(10, 20);

0131141e  push        14h  

01311420 push 0ah

01311422 call _fun1 (0131118bh)

引數順序是10,20,在這裡彙編指令首先push 14h也就是20,再push 0ah也就是10。從這裡可以看出來,引數入棧的順序是從右向左入棧的。

首先push的是ebp-18h的四個位元組,也就是tmp2.b,然後是tmp2位址上取四個位元組,就是tmp2.a。再push的是ebp-8的四個位元組也就是tmp1.b,然後是tmp1位址上取四個位元組,也就是tmp1.a。由此可見,函式引數是8個位元組的時候,是利用push入棧的方式將引數傳遞。

#include int sum(int a,int b)

int main()

轉到反彙編,看到呼叫點的彙編指令:

rt = sum(a1,b1);

0040108d mov eax,dword ptr [ebp-8]

00401090 push eax

00401091 mov ecx,dword ptr [ebp-4]

00401094 push ecx

00401095 call @ilt+0(sum) (00401005)

0040109a add esp,8

0040109d mov dword ptr [ebp-0ch],eax

call指令在呼叫時有兩步:首先壓入下一行指令位址,其次jmp跳轉到sum函式棧幀中。

可以看到,形參變數開闢了記憶體空間,這是在呼叫方開闢的。整個過程:

①在棧上壓入引數。

②執行call指令,在棧上壓入函式的返回位址。

③壓入ebp暫存器的值。

④將esp暫存器的值賦給ebp暫存器。

⑤減小esp暫存器的值,為區域性變數分配空間。

⑥執行函式**。

⑦將ebp暫存器的值賦給esp暫存器,等於**了區域性變數的空間。

⑧彈出棧頂的值,賦給ebp,即將第③步中壓入的值重新賦給ebp。

⑨執行ret指令,彈出棧頂的返回位址。如果被呼叫函式負責**引數的空間,則需要增加esp的值。

struct tmp

;//大小為8位元組

struct tmp fun1(int a, int b)

int main()

將**執行到函式返回值出,檢視其彙編**

return c;

00b7142a mov eax,dword ptr [c]

00b7142d mov edx,dword ptr [ebp-8]

將**執行到接收返回值處,檢視其彙編**

c = fun1(a,b);

……00d63c44 call fun1 (0d611efh)

00d63c49 add esp,8

00d63c4c mov dword ptr [c],eax

00d63c52 mov dword ptr [ebp-20h],edx

在接收返回值時候,將暫存器的值寫入到接收返回值的變數中。

函式棧幀的回退分為兩步,一步是函式棧幀的回退,另一步時函式引數的清除。

函式棧幀回退匯編碼如下

}00ec13e0 pop edi 將棧幀開闢時候入棧的暫存器出棧

00ec13e1 pop esi

00ec13e2 pop ebx

00ec13e3 mov esp,ebp 讓esp = ebp

00ec13e5 pop ebp 讓ebp等於棧幀開闢時候入棧的main棧幀,並將其出棧

00ec13e6 ret 返回

經過上面的過程,棧幀就已經回退到了main函式,也就是呼叫方的棧幀。

下一步,函式引數的清除

00ec1484 call _fun1 (0ec118bh)

00ec1489 add esp,8 讓esp+8清除引數記憶體。

函式呼叫過程

每乙個未執行完的函式都對應著乙個棧幀,系統為單個函式分配的那部分棧空間就叫做棧幀,棧幀儲存了函式的資訊。以下面的 為例,通過彙編 的執行過程介紹棧幀建立和銷毀的過程 include int add int x,int y int main 從main函式建立自己的棧幀開始 其他內容先忽略 初始狀態 ...

函式呼叫過程

c語言種有三種迴圈 do.while while for 初始化 條件判斷 步進 主函式 main 庫函式自定義函式函式的發明,使得變成可以以函式為單位進行模組化,叫做面向過程。軟體工程中,有 高內聚,低耦合 的要求。函式就是為了實現以上要求發明的產物。函式是面向過程的 介面 其介面包含了 引數 返...

函式呼叫過程

引數代入順序 引數入棧的順序是從右向左入棧的。8位元組的引數代入 push入棧的方式將引數傳遞 8位元組的引數代入 先在main函式的棧頂向上移動12位元組,然後將引數的資料拷貝到main函式棧頂開闢的記憶體。int fun1 int a,int b int main 第一步進行函式引數入棧,如圖 ...