棧幀與函式呼叫過程

2021-08-13 09:21:44 字數 2152 閱讀 2450

程式的位址空間圖中,從下向上,位址不斷增長,從0x00000000到0xffffffff。

code:**區,儲存**

字元、串常量區:儲存不能被修改的常量

init,uninit:全域性區,分別為初始化全域性區,和未初始化全域性區,儲存全域性變數

heap:堆,使用malloc在堆申請空間,在堆上建立的變數使用完畢後要手動釋放空間

棧:在離堆較遠處的一塊空間叫做棧,用於存放臨時變數,函式呼叫時形成棧幀,函式呼叫完成時,銷毀棧幀

注:堆和棧相對而生,即棧底在較高位址處,在不斷的使用對空間,建立臨時變數時,棧頂向低位址處移動,堆則相反
棧幀:在函式呼叫的過程中,要為函式開闢空間,用於本次函式呼叫中臨時變數的儲存、現場保護,這塊棧空間稱為棧幀。

棧幀的維護離不開兩個暫存器,ebp,esp,當main函式開始執行時,形成main函式的棧幀,esp指向棧幀的棧頂,ebp指向棧幀的棧底,在這個過程中ebp和esp相當於指標

在c語言中,main函式被_tmaincrtsartup函式呼叫,當有如下**時:

#include

int main()

當main函式呼叫時,要開闢棧空間,畫出棧幀圖:

為了清楚觀察這一過程,用vc6.0轉到匯程式設計序,可以清楚地看出,當開闢棧幀完成時,經過小麵兩行彙編**,用ebp完成a,b的建立並賦值,ebp-4和ebp-8的原因是整形變數需要四個位元組的空間,

如果在建立完成a,b之後,要進行add(a,b),完成a和b相加,並返回結果,**如下:

當開始調函式的時候,將a,b再次建立乙份放在main函式的棧幀外面,esp不斷移動,注意,先建立的b,即在add的引數裡,從右向左依次例項化,圖如下:

進來之後

將main的ebp存的值壓入棧內

ebp指向esp的位置

esp-44h

經過前兩條指令就形成了add函式的棧幀

add建立z的方式和在main函式中建立a,b的方式一致

棧幀圖如下:

接下來

然後通過ebp找到 形參a,b將a+b賦值給z

將z中的值放在eax通用暫存器中

此時,add函式已經執行完成

不斷進行pop指令,edp不斷向上移,即所指向位址不斷增加

然後將esp指向ebp所指向的位置

然後在進行pop指令將棧頂元素彈人ebp,因為這是棧頂的值是原來main函式ebp的值,所以ebp再次指向main函式的棧幀的底部,如圖:

最後進行ret指令,返回call的下一條指令除

call的功能:

1、彈出棧頂

2、彈出的值放入eip中

給esp+8,esp再次指向main函式的棧幀頂部,main函式的棧幀恢復完成

再把eax中的值(z即a+b)放在c內

函式呼叫完成,返回值收,列印

函式呼叫過程(棧幀)

眾所周知,程式每呼叫乙個函式,系統都會為其開闢一塊空間,當它返回時,才收回這塊空間。程式崩潰有一部分原因就是因為無限制的呼叫函式,卻沒有及時返回,導致記憶體空間不夠。為了更好的維護這一塊空間 通常稱為棧空間 我們需要了解兩個暫存器,乙個為 esp 指向棧頂的指標 乙個為 ebp 指向棧底的指標 棧空...

函式棧幀(呼叫過程)

函式棧幀就是在呼叫函式是為其在棧空間上開闢了一段空間,指向過程呼叫,乙個過程呼叫包括將資料 以過程引數和返回值的形式 和控制從 的一部分傳遞到另一部分。我們以以下 為例講解整個函式呼叫過程 int my add int x,int y int main 一 呼叫main 函式 我們從main 函式的...

棧幀與函式呼叫過程分析

乙個c c 編譯的程式占用的記憶體分為以下幾個部分 1.棧區 stack 由編譯器自動分配和釋放,存放函式的引數值,區域性變數的值,返回資料,返回位址等。操作方式類似於資料結構中的棧。2.堆區 heap 一般由程式設計師分配和釋放,若程式設計師不釋放,程式結束時可能由作業系統 與資料結構中的堆是兩碼...