當前位置:才華齋>計算機>C語言>

C函式的呼叫過程

C語言 閱讀(3.02W)

在C程式碼中通過asm或__asm__嵌入一些彙編程式碼,如進行系統呼叫,使用暫存器以提高效能能,需要對函式呼叫過程中的堆疊幀(Stack Frame)、CPU暫存器、GCC inlie assembly等了如指掌。現在看看函式呼叫過程吧。

C函式的呼叫過程
C函式的呼叫過程

  1. Linux 程序虛擬地址空間

以32位作業系統為例,下面是Linux程序地址空間佈局:

32位虛擬地址空間的高1GB的空間是留給作業系統核心的,棧由高地址到低地址向下增長,堆由低地址到高地址向上增長。

C中如 malloc 等分配的`記憶體在堆中分配。初始化了的靜態變數和全域性變數放在Data段中。未初始化的全域性變數和區域性靜態變數放在Bss段中,更準確的說是在Bss段為它們預留了空間。非靜態區域性變數是在函式呼叫過程中暫存在棧上的。

 2. 函式的堆疊幀

棧在程式執行中具有舉足輕重的地位。最重要的,棧儲存了一個函式呼叫所需要的維護資訊,被稱為堆疊幀(Stack Frame),一個函式(被調函式)的堆疊幀一般包括下面幾個方面的內容:

(1) 函式引數,預設呼叫慣例情況下從右向左的順序依次把引數壓入棧中。由函式呼叫方執行。

(2) 函式的返回地址,即呼叫方呼叫此函式(如call func1)的下一條指令的地址。函式呼叫方(call指令)執行。

(3) 儲存呼叫方函式的EBP暫存器,即將呼叫方函式的EBP壓入堆疊,並令EBP指向此棧中的地址:pushl %ebp; movl %esp, %ebp。由被調函式執行。

(4) 上下文:儲存在函式呼叫過程中需要保持不變的暫存器(函式呼叫方的),如ebx,esi,edi等。由被調函式執行。

(5) 臨時變數,如非靜態區域性變數。

下面是一個函式的堆疊幀結構圖:

壓入函式引數和返回地址的過程是由函式呼叫方在呼叫函式之前將其壓入棧中,每個函式執行後首先要執行的就是把函式呼叫方的EBP暫存器壓入棧中,之後是在棧上開闢一些空間存放區域性變數,最後把要儲存的暫存器壓入棧中。