函式的呼叫,棧楨的建立及銷毀

2021-08-19 14:10:22 字數 2014 閱讀 2553

下面我們主要從棧的層面深入了解c語言中函式呼叫的過程。

下面我用乙個簡單的程式說明:

#include

#include

int add(int x, int y)

int main()

011e1880

pop edi

011e1881

pop esi

011e1882

pop ebx

011e1883

add esp,0e4h

011e1889 cmp ebp,esp

011e188b call __rtc_checkesp (011e112ch)

011e1890

mov esp,ebp

011e1892

pop ebp

011e1893

ret

add函式彙編**:

int add(int x, int y)

011e1731

pop edi

011e1732

pop esi

011e1733

pop ebx

011e1734

mov esp,ebp

011e1736

pop ebp

011e1737

ret

首先,我們在這裡必須的先了解倆個暫存器:

ebp

———棧底的位址

esp

———棧頂的位址

每乙個函式的呼叫都需要在棧上開闢空間,而開闢的空間都由ebp和esp維護

而且ebp和esp維護的是呼叫main函式的maincrtstartup函式的空間。

接下來我們進去main函式痕跡彙編**一步一步來了解函式呼叫的過程以及棧的建立和銷毀:

int main()

這裡add函式的呼叫同main函式呼叫過程相同,執行上端**後得到結果如圖示:

棧的銷毀:

011e1731  pop         edi  

011e1732 pop esi

011e1733 pop ebx

pop就相當於出棧的意思,esp此時指向ebx下面的空間,這三個位址相當於被**;

011e1734

mov esp,ebp

011e1736

pop ebp

011e1737

ret

這裡把ebp的值給esp,然後再將ebp出棧,這裡的ebp是main函式的ebp,ret指令要返回值,首先把棧頂call執行下一條指令的位址出棧,然後緊接著跳到下面這一行的位址。這也就是為什麼把之前的位址儲存起來,起一定的返回作用。

011e1850

add esp,8

esp+8直接把定義的形參跳了過去,到這一步的時候,add棧幀已經被銷毀了。

011e1853

movdword

ptr[ebp-0ch],eax

eax裡存放的是add函式裡的的值,把eax的值放入ebp-0ch,ret就把z的值返回了。

在棧幀銷毀的過程中返回值是通過暫存器返回的。

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

函式在呼叫的過程中分為三步,第一步是函式的呼叫,第二步是執行函u數體,第三步是返回。第一步 函 數的呼叫 2.將實參從後往前依次入棧 3.跳轉到函式體處。第二部 函式體執行 1.如果函式體中定義了變數,將變數入棧 2.將每乙個形參用實參的值取代,執行函式體的功能 3.將函式體中的變數和儲存到棧中的實...

函式呼叫程序 棧楨

函式呼叫過程 棧楨 例 剖析 比較兩個數之間的大小關係,並把較大數返回 的呼叫原理 intmax intx,inty intmain 分析 圖一 main函式是被maincrtstartup呼叫的,所以main函式棧楨的ebp 1存放的是maincrtstartup棧楨ebp 觀察上圖maincrt...

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

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