1. 程式人生 > >C++基礎知識:c 函式呼叫過程原理及函式棧幀分析

C++基礎知識:c 函式呼叫過程原理及函式棧幀分析

1.關於棧

  首先必須明確一點也是非常重要的一點,棧是向下生長的,所謂向下生長是指從記憶體高地址->地地址的路徑延伸,那麼就很明顯了,棧有棧底和棧頂,那麼棧頂的地址要比棧底低。對x86體系的CPU而言,其中

  ---> 暫存器ebp(base pointer )可稱為“幀指標”或“基址指標”,其實語意是相同的。

  ---> 暫存器esp(stack pointer)可稱為“ 棧指標”。

  要知道的是:

  ---> ebp 在未受改變之前始終指向棧幀的開始,也就是棧底,所以ebp的用途是在堆疊中定址用的

  ---> esp是會隨著資料的入棧和出棧移動的,也就是說,esp始終指向棧頂。

  見下圖,假設函式A呼叫函式B,我們稱A函式為"呼叫者",B函式為“被呼叫者”則函式呼叫過程可以這麼描述:

  (1)先將呼叫者(A)的堆疊的基址(ebp)入棧,以儲存之前任務的資訊。

  (2)然後將呼叫者(A)的棧頂指標(esp)的值賦給ebp,作為新的基址(即被呼叫者B的棧底)。

  (3)然後在這個基址(被呼叫者B的棧底)上開闢(一般用sub指令)相應的空間用作被呼叫者B的棧空間。

  (4)函式B返回後,從當前棧幀的ebp即恢復為呼叫者A的棧頂(esp),使棧頂恢復函式B被呼叫前的位置;然後呼叫者A再從恢復後的棧頂可彈出之前的ebp值(可以這麼做是因為這個值在函式呼叫前一步被壓入堆疊)。這樣,ebp和esp就都恢復了呼叫函式B前的位置,也就是棧恢復函式B呼叫前的狀態。

  這個過程在AT&T彙編中通過兩條指令完成,即:

  leave

  ret

  這兩條指令更直白點就相當於:

  mov %ebp , %esp

  pop %ebp

\
轉自:http://www.examw.com/biancheng/c/190531/