c語言函式棧幀的建立和銷毀過程詳解

2022-09-24 20:00:10 字數 2319 閱讀 8433

目錄

一般計算機內通用暫存器包括eax,ebx,ecx,edx,esi,edi,esp,edp,其中esp,ebp這兩個暫存器是用來存放位址的,這兩個位址就是用來維護函式棧幀的

我們知道c語言中函式都是被呼叫的,main函式裡面能呼叫其他函式,其實main函式也是被別的函式呼叫的。main函式是在 _tmaincrtsartup 函式中被呼叫的,_tmaincrtsartup函式又是在maincrtsartup函式中被呼叫。

每一次函式呼叫都是乙個函式呼叫過程,這個過程要為函式開闢棧空間,用於本次函式的呼叫中臨時變數的儲存、現場保護,也叫函式棧幀。棧幀也叫過程活動記錄,是編譯器用來實現過程/函式呼叫的一種資料結構。

push 壓棧:給棧頂放上乙個元素

pop 出棧:從棧頂刪除乙個元素

函式棧幀結構如下:

其中esp為棧頂指標,ebp為棧底指標,他們共同來維護函式棧幀。

為了描述函式棧幀的建立和銷毀我們以乙個簡單程式為例

#define _crt_secure_no_warnings 1

#include

int add(int x, int y)

int main()

當進入main函式前,esp,ebp在如下位置

我們此時可以進入除錯模程式設計客棧式然後進入反彙編模式看下彙編**從而觀察main函式棧幀的建立

這裡是將ebp壓棧(用來記錄上乙個ebp方便函式銷毀時找到上乙個函式的位置),然後將esp的值傳給ebp,在將esp的內容減去0e4h,從而為main函式建立了乙個棧幀,並且將ebx,sei,edi的值進行壓棧。效果如下

這裡是將ebp-0e4h的值載入到edi裡面,然後將39h放到ecx暫存器裡,再將0cccccccch放到eax暫存器裡,最後將edi這個位址下面的39h個位元組資料的值全部置為cccccccc.

這段彙編**時將14h賦值到ebp-8的空間裡面,將0ah賦值到ebp-14h的空間裡面,將0賦值到ebp-20h的空間裡面.

然後進入c = add(a,b)語句,首先將ebp-14h的值放到eax暫存器中在將eax的值進行壓棧操作,再將ebp-8的值放到ecx暫存器中在將ecx的值進行壓棧操作。

下面中綠色框裡eax應該是10,ecx是20,畫圖時寫反了實在是抱歉

這裡是跳轉到add函式,並將下一條語句的位址壓入棧內

000e17c0 push ebp //記錄上乙個ebp內容

000e17c1 mov ebp,esp //將esp的值賦給ebp

000e17c3 sub esp,0cch //將0cch賦給esp,為add建立棧幀

000e17c9 push ebx

000e17ca push esi

000e17cb push edi

000e17cc lea edi,[ebp+ffffff34h]

000e17d2 mov ecx,33h

000e17d7 mov eax,0cccccccch

000e17dc rep stos dword ptr es:[edi]

000e17de mov ecx,0ec003h //與前面類似

000e17e3 call 000e1307 //進入add函式

7: int z = 0;

000e17e8 mov dword ptr [ebp-8],0 //將0賦給ebp-8的內容

8: z = x + y;

000e17ef mov eax,dword ptr [ebp+8] //將a的值賦給eax暫存器

000e17f2 add eax,dword ptr [ebp+0ch] //將b+a的值賦給eax

000e17f5 mov dword ptr [ebp-8],eax /www.cppcns.com/將eax的值賦給ebp-8的內容dwttrrruuj裡面

9: return z;

000e17f8 mov eax,dword ptr [ebp-8] //將ebp-8的內容裡面賦給eax

至此add函式功能執行完成,接下來開始返回,也就是進行add函式棧幀銷毀

首先分別將edi,esi,ebx進行出棧,然後將esp加上0cch也就是回到ebp的位置,然後將ebp的值賦給esp,再將ebp進行出棧操作(這樣就能回到原來的main函式的ebp位置從而將add的棧幀空間還給作業系統)

後面是main函式的銷毀過程,流程和add銷毀一樣,這裡就不在過多贅述。

C語言 函式的呼叫過程及棧幀的建立和銷毀

一 說起函式呼叫,我們可能很快就想到 程式從main函式走起,遇到呼叫函式的語句,就跳轉到此函式所在的語句塊執行此函式,執行完之後再返回main函式繼續執行程式。但是這只是籠統的描述,其實在函式內部,函式呼叫要經過一系列的複雜的過程,下面為大家一一詳細敘述。1.說到函式呼叫,我們不可避免的要說到棧幀...

函式的呼叫過程 棧幀的建立和銷毀

首先我們要了解一些概念。1.棧 stack 由編譯器自動分配釋放,存放為執行函式而分配的區域性變數 函式引數 返回函式 返回位址等。操作方式類似於資料結構中的棧。棧向下生成 先定義的位址高,後定義的位址低 2.堆 heap 由程式設計師分配釋放 若程式設計師不釋放,程式結束時可能由os 分配方式類似...

函式的呼叫過程,棧幀的建立和銷毀

我們大家學習c語言肯定都知道函式,但大家可能都只會用函式,對它的了解只是上層的,並不知道它的呼叫過程,今天我們就一起來深入的研究一下函式的呼叫過程。首先,我們要知道的是,在函式呼叫時,程式將使用乙個執行時堆疊,它裡邊存區域性變數和返回位址,執行時堆疊由ebp 存放維護這個棧的棧底指標 和esp 存放...