以下面一段代碼爲例,說一說函數的調用過程,棧幀的創建與銷燬。
這段代碼要在VC6.0下調試,因爲VC6.0對這部分的處理簡單些,利於學習使用。
#include<stdio.h>
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 258;
int b = 20;
int ret = Add(a, b);
printf("ret = %d\n", ret);
return 0;
}
調試以上代碼,看調用堆棧窗口,我們可以看到main函數在 __tmainCRTStartup函數中被調用,而__tmainCRTStartup函數是在mainCRTStartup中被調用。
每一次函數調用都是一個過程,這個過程我們叫做:函數的調用過程。
這個過程要爲函數開闢棧空間,用於本次函數調用中臨時變量的保存、調用現場的保護。這塊棧空間我們稱之爲函數棧幀。
想要了解清楚函數的調用過程,棧幀是如何創建和銷燬的,首先要了解一些彙編的知識。
ebp和esp兩個寄存器,在函數調用過程中這兩個寄存器存放了維護這個棧的棧底和棧頂的指針。
例如:調用main函數,我們爲main函數分配棧幀空間,棧幀維護如下:
ebp存放指向棧幀棧底的地址,esp存放指向棧幀棧頂的地址。
下面來看調試模式下的反彙編窗口:(以下截圖均來自VS2013,因博主木有安裝vc6.0)
1.從main函數開始,先來看main函數棧幀的創建
2. 2.接下來看Add函數的調用
執行call指令,按下F11,如下:
再按F11,來到Add函數的執行代碼處:
接下來是Add函數返回部分,Add函數棧幀銷燬過程:
以上就是函數調用的全部過程。