C语言函数调用完整过程
C語言函數調用詳細過程
函數調用是步驟如下:
按照調用約定傳參
調用約定是調用方(Caller)和被調方(Callee)之間按相關標準
對函數的某些行為做出是商議,其中包括下面內容:
傳參順序:是從左往右傳還是從右往左
傳參方式:是用寄存器傳還是使用內存傳
平棧方式:是調用方平棧還是被調方平棧
返回值的傳遞方式:是用寄存器傳還是使用內存傳
什么是堆桟?
一個程序運行的時候,它的進程的地址空間一般可以分為四塊:
代碼區,數據區,堆,棧,每塊功能如下:
| 區域 | 功能 |
|---|---|
| 代碼區 | 存放函數被編譯后的二進制可執行代碼 |
| 數據區 | 只讀區:存放常量,例如:常量字符串,const修飾的全局變量等 可讀寫區:存放全局變量和靜態變量 |
| 堆 | 除去其他三個區域,剩下的都是堆,不連續 |
| 棧 | 存放函數運行時所需的參數,寄存器環境,返回值,局部變量 |
以下面代碼為例:
int TestFunction(char szBuff[],int nSize)
{
for (int iIndex = 0; iIndex < nSize; iIndex++)
{
szBuff[iIndex] = 'x';
}
return 3;
}
int main()
{
char szBuff[32] = { "sfjdlskfjl" };
int nRet = TestFunction(szBuff, 32);
return 0;
}
函數參數參數傳遞:
從上圖中可以看出函數參數入棧
保存返回地址(緊挨著被調用函數的下一行可執行代碼的內存地址)
從上圖中可以看出函數調用完成后,緊挨著的第一條指令為:
00EB175B add esp,8
所以,參數傳遞完成后就是返回值入棧:
程序流程轉移到被調用函數地址處
保存調用方棧底
切換到當前函數(被調用函數)的棧底
調用方棧底保存完成后,當前的棧頂(ESP記錄的地址)就成為被調用函數的棧底
為局部變量分配空間
這里程序為調試版本,所以為局部變量分配的空間比較大,在Release版本中
會根據局部變量實際所需空間來分配大小
保存寄存器環境
這里一共保存了3個寄存器,共12字節,在Release版本下,只保存兩個
在Debug版程序中(有/Zi(帶有調試信息)和/Od(禁止優化)編譯命令),除了為
局部變量分配較大的內存空間外,還會將分配的局部變量空間全部置為0xCC:
這種填充方式比較直觀,能夠讓我們在調試時直觀的觀察到是否發生越界等錯誤
開始執行函數體代碼
此時當前函數的棧的內存布局如下:
恢復寄存器環境
釋放分配的局部變量空間
只是將當前的棧底指針(EBP)的值賦值給棧頂指針(ESP)就完成了:
恢復調用方棧底
平棧或者返回
如果是_fastcall,_stdcall調用約定,那么被調用函數平棧后,取出返回地址
函數流程轉移到調用方
其他調用約定則是直接取出保存的返回地址,函數流程返回到調用方,又調用方
平棧
總結
以上是生活随笔為你收集整理的C语言函数调用完整过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新房装修刮漆好了后墙面开裂了,全部铲掉重
- 下一篇: FFTW(快速傅里叶变换)中文参考