函式呼叫棧比較有意思

2021-04-12 16:38:48 字數 1093 閱讀 3344

理解呼叫棧最重要的兩點是:棧的結構,ebp暫存器的作用。

首先要認識到這樣兩個事實:

2、幾乎所有本地編譯器都會在每個函式體之前插入類似如下指令:push ebp; mov ebp esp;

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

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

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

| 引數3                |

| 引數2                |

| 引數1                |

| 返回位址             |

-| 上一層[ebp]          | <-------- [ebp]

「push ebp」「mov ebp esp」這兩條指令實在大有深意:首先將ebp入棧,然後將棧頂指標esp賦值給ebp。「mov ebp esp」這條指令表面上看是用esp把ebp原來的值覆蓋了,其實不然——因為給ebp賦值之前,原ebp值已經被壓棧(位於棧頂),而新的ebp又恰恰指向棧頂。

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

一般而言,ss:[ebp+4]處為返回位址,ss:[ebp+8]處為第乙個引數值(最後乙個入棧的引數值,此處假設其占用4位元組記憶體),ss:[ebp-4]處為第乙個區域性變數,ss:[ebp]處為上一層ebp值。

由於ebp中的位址處總是「上一層函式呼叫時的ebp值」,而在每一層函式呼叫中,都能通過當時的ebp值「向上(棧底方向)能獲取返回位址、引數值,向下(棧頂方向)能獲取函式區域性變數值」。

如此形成遞迴,直至到達棧底。這就是函式呼叫棧。

編譯器對ebp的使用實在太精妙了。

從當前ebp出發,逐層向上找到所有的ebp是非常容易的:

unsigned int _ebp;

__a** _ebp, ebp;

while (not stack bottom)

如果要寫乙個簡單的偵錯程式的話,注意需在被除錯程序(而非當前程序——偵錯程式程序)中讀取記憶體資料。 

函式呼叫棧比較有意思

昨天和海洋一塊研究了下函式呼叫棧,順便寫兩句。不足或錯誤之處請包涵!理解呼叫棧最重要的兩點是 棧的結構,ebp暫存器的作用。首先要認識到這樣兩個事實 2 幾乎所有本地編譯器都會在每個函式體之前插入類似如下指令 push ebp mov ebp esp 棧底方向,高位位址 引數3 引數2 引數1 返回...

函式呼叫棧比較有意思

昨天和海洋一塊研究了下函式呼叫棧,順便寫兩句。不足或錯誤之處請包涵!理解呼叫棧最重要的兩點是 棧的結構,ebp暫存器的作用。首先要認識到這樣兩個事實 2 幾乎所有本地編譯器都會在每個函式體之前插入類似如下指令 push ebp mov ebp esp 棧底方向,高位位址 引數3 引數2 引數1 返回...

程式設計是比較有意思的事情

這些天一直在實驗室幹活,忙得不行,所以也沒時間來寫部落格,今天有時間了,先寫點對程式設計的體會。最近逐漸感覺程式設計是比較有意思的事情,它有意思在於讓我們比較有創造力。記得上個學期一來,由於深感教育網上國外 要上 上國內網 特別是教育網的 為了速度又要去掉 的麻煩,於是就寫了乙個ie的 指令碼,到網...