日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C/C++函数调用的压栈模型

發(fā)布時(shí)間:2024/1/23 c/c++ 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C/C++函数调用的压栈模型 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? 函數(shù)調(diào)用的壓棧模型對于我們學(xué)習(xí)C語言非常重要,最直觀的體現(xiàn)在我們后面要學(xué)的函數(shù)的遞歸,函數(shù)的遞歸就充分利用的函數(shù)的壓棧模型。

? ??

? ? 當(dāng)函數(shù)從入口函數(shù)main函數(shù)開始執(zhí)行時(shí),編譯器會將我們操作系統(tǒng)的運(yùn)行狀態(tài),main函數(shù)的返回地址、main的參數(shù)、main函數(shù)中的變量、進(jìn)行依次壓棧;當(dāng)main函數(shù)開始調(diào)用fa()函數(shù)時(shí),編譯器此時(shí)會將main函數(shù)的運(yùn)行狀態(tài)進(jìn)行壓棧,再將fa()函數(shù)的返回地址、fa函數(shù)的參數(shù)、fa定義變量依次壓棧;當(dāng)fa調(diào)用fb的時(shí)候,編譯器此時(shí)會將fa函數(shù)的運(yùn)行狀態(tài)進(jìn)行壓棧,再將fb函數(shù)的返回地址、fb函數(shù)的參數(shù)、fb定義變量依次壓棧。

? ??

? ? 當(dāng)函數(shù)fb運(yùn)行完成后,fb所有的壓棧都會被編譯器釋放掉,編譯器再從棧中接收到fa函數(shù)的運(yùn)行狀態(tài)后,銜接調(diào)用fb函數(shù)之前的操作,繼續(xù)執(zhí)行,同理,fa執(zhí)行完后,編譯器對main函數(shù)的處理也相同。

? ? 一個函數(shù)可以在棧上分配內(nèi)存,也可以在堆上分配內(nèi)存,更可以在全局區(qū)域分配內(nèi)存,因此理解內(nèi)存從哪里來,對于我們函數(shù)參數(shù)的傳遞,變量的調(diào)用異常重要。

? ? fb函數(shù)在棧上分配的內(nèi)存,不能被fa和main函數(shù)所調(diào)用,因?yàn)樗鼤趂b函數(shù)執(zhí)行完后被編譯器釋放掉;而fb函數(shù)使用new和malloc在堆上分配的內(nèi)存或者全局區(qū)分配的內(nèi)存,只要不被程序員自己釋放掉,是可以被fa和main函數(shù)所調(diào)用的。

? ? 轉(zhuǎn)自:https://blog.csdn.net/m0_37717595/article/details/80368411

?

--------------------------------------------------------------------------------------

函數(shù)壓棧的過程(轉(zhuǎn) 知乎)

例如:

void func_A(arg_A1, arg_A2); void func_B(arg_B1, arg_B2);int main(int argc, char *argv[], char **envp) {func_A(arg_A1, arg_A2); }void func_A(arg_A1, arg_A2) {var_A;func_B(arg_B1, arg_B2); }void func_B(arg_B1, arg_B2) {var_B1;var_B2; }

在main函數(shù)調(diào)用func_A的時(shí)候,首先在自己的棧幀中壓入函數(shù)返回地址,然后為func_A創(chuàng)建棧幀并壓入系統(tǒng)棧;

在func_A調(diào)用func_B的時(shí)候,同樣先在自己的棧幀中壓入函數(shù)返回地址,然后為func_B創(chuàng)建新棧幀并壓入系統(tǒng)棧;

在func_B返回時(shí),func_B的棧幀被彈出系統(tǒng)棧,func_A棧幀中的返回地址被"露"在棧頂,此時(shí)處理器按照這個返回地址重新跳到func_A代碼區(qū)中執(zhí)行;

在func_A返回時(shí),func_A的棧幀被彈出系統(tǒng)棧,main函數(shù)棧幀中的返回地址被"露"在棧頂,此時(shí)處理器按照這個返回地址跳到main函數(shù)代碼區(qū)中執(zhí)行。

在實(shí)際運(yùn)行中,main函數(shù)并不是第一個被調(diào)用的函數(shù),程序被裝入內(nèi)存前還有一些其他操作,上圖只是棧在函數(shù)調(diào)用過程中所起作用的示意圖。

ESP:棧指針寄存器(extended stack pointer),其內(nèi)存放著一個指針,該指針永遠(yuǎn)指向系統(tǒng)棧最上面一個棧幀的棧頂。

EBP:基址指針寄存器(extended base pointer),其內(nèi)存放著一個指針,該指針永遠(yuǎn)指向系統(tǒng)棧最上面一個棧頂?shù)牡撞俊?/p>

函數(shù)棧幀:ESP和EBP之間的內(nèi)存空間為當(dāng)前棧幀,EBP標(biāo)識了當(dāng)前棧幀的底部,ESP標(biāo)識了當(dāng)前棧幀的頂部。

EIP:指令寄存器(extended instruction pointer),其內(nèi)存放著一個指針,該指針永遠(yuǎn)指向下一條待執(zhí)行的指令地址。

函數(shù)調(diào)用大致包括以下步驟:

1.參數(shù)入棧:將參數(shù)從右向左依次壓入系統(tǒng)棧中;

2.返回地址入棧:將當(dāng)前代碼區(qū)調(diào)用指令的下一條指令地址壓入棧中,供函數(shù)返回時(shí)繼續(xù)執(zhí)行;

3.代碼區(qū)跳轉(zhuǎn):處理器從當(dāng)前代碼區(qū)跳轉(zhuǎn)到被調(diào)用函數(shù)的入口處。

4.棧幀調(diào)整:具體包括:

? ? 保存當(dāng)前棧幀狀態(tài)值,已備后面恢復(fù)本棧幀時(shí)使用(EBP入棧);

? ? 將當(dāng)前棧幀切換到新棧幀。(將ESP值裝入EBP,更新棧幀底部)

? ? 給新棧幀分配空間。(把ESP減去所需空間的大小,抬高棧頂)

?

轉(zhuǎn)自:http://www.cnblogs.com/wsw-seu/p/8278547.html

?

總結(jié)

以上是生活随笔為你收集整理的C/C++函数调用的压栈模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。