函式呼叫棧

2021-06-06 03:22:38 字數 1427 閱讀 2989

當程式進行函式呼叫的時候,系統會用到下面三種暫存器:

3.ebp:ebp暫存器裡儲存的是棧基址,是在函式呼叫之前,由esp賦值給ebp的。

+| (棧底方向,高位位址) |

| ......................|

| ......................|     // call fun(arg1, arg2, arg3) --> 修改esp,棧向下增長,引數入棧,返回位址入棧

| arg3|

| arg2|

| arg1|

| 返回位址|

| 上一層ebp    |     // push ebp;move ebp esp;新ebp所指向的位置就在此處,而此處非常巧妙的又存著上一層ebp的位置

| 區域性變數1     |

| 區域性變數2     |

|.......................|

每次呼叫函式時候,先壓函式引數(從右往左順序壓),再壓入函式呼叫下條指令的位址(由call完成)。

接著進入呼叫函式體中,先執行push ebp; mov ebp esp;(一般已經由編譯器加入到函式頭中了),接著就是吧函式體中的區域性變數壓入棧中。

push ebp;mov ebp esp這兩條指令大有深意:首先將ebp入棧,然後將esp賦值給ebp。

mov ebp esp這條指令表面上看是用esp把ebp原來的值覆蓋了,其實不然——因為給ebp賦值之前,原ebp值已被壓棧(位於棧頂),而新的ebp又恰恰指向棧頂。

此時ebp暫存器已處於乙個很重要的地位,該暫存器中儲存著棧中的乙個位址,從該位址為基準,向上(棧底方向)能獲取返回位址、引數值,向下(棧頂方向)能獲取函式區域性變數值,而該位址處又儲存著上一層函式呼叫時的ebp值!

一般而言,

ss:[ebp+4]處為返回位址,

ss:[ebp+8]處為第乙個引數值(最後乙個入棧的引數值,此處假設其占用4位元組記憶體),

ss:[ebp-4]處為第乙個區域性變數,

ss:[ebp]處為上一層ebp值。

由於ebp存放的是乙個位址,該位址的內容總是「上一層函式呼叫時的ebp值」,所以當函式呼叫返回時,一方面可以通過[ebp+4]取得返回位址(也就是下一條指令的位址),另一方面,也可以獲取上一層的ebp值,並將該值賦值給esp,實現了棧的回退。

棧 函式呼叫

編譯以下程式,分析此程式以得出棧的精髓 1 主函式被上層呼叫者呼叫後,執行push ebp,esp 4 因為ebp入棧 ebp值沒有改變,值得注意的是剛開始分配站的時候,第乙個入棧的是return,主函式的返回位址,然後是ebp 2 然後是mov ebp,esp,將esp的值賦給ebp,該語句未執行...

函式呼叫 函式棧

函式呼叫大家都不陌生,呼叫者向被呼叫者傳遞一些引數,然後執行被呼叫者的 最後被呼叫者向呼叫者返回結果,還有大家比較熟悉的一句話,就是函式呼叫是在棧上發生的,那麼在計算機內部到底是如何實現的呢?對於程式,編譯器會對其分配一段記憶體,在邏輯上可以分為 段,資料段,堆,棧 段 儲存程式文字,指令指標eip...

函式呼叫棧恢復

cdecl 引數從右到左壓入,由呼叫者彈出,函式名 前置 stdcall 引數從右到左壓入,由被呼叫者彈出,函式名無變化 pascal 引數從左到右壓入,由呼叫者彈出,函式名大寫 fastcall 引數從左到右壓入,由被呼叫者彈出,函式名 前置 void fun 1,2 1。cdecl 是這樣的 p...