程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 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

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved