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

2021-08-10 18:20:32 字數 1968 閱讀 4546

首先我們要了解一些概念。

1.棧(stack)

由編譯器自動分配釋放,存放為執行函式而分配的區域性變數、函式引數、返回函式、返回位址等。操作方式類似於資料結構中的棧。

棧向下生成(先定義的位址高,後定義的位址低)

2.堆(heap)

由程式設計師分配釋放

,若程式設計師不釋放,程式結束時可能由os**。分配方式類似於鍊錶。

堆向上生成(先定義的位址低,後定義的位址高)

3.文字常量區

(唯讀)

常量字串存放處。程式結束後

由系統釋放

。執行時檢測。

4.程式**區

(唯讀)

存放函式體(類成員函式和全域性函式)的二進位制**

5.全域性區(static)

分為已初始化全域性資料區(init data)和未初始化全域性資料區(uninit data)

存放全域性變數、靜態資料、常量。程式結束後

由系統釋放

。具體情況如下圖:

接下來我們來具體了解棧幀,來看一段**:

由上圖我們可以看出,

main函式並不是函式啟動開始第乙個被呼叫的函式,但它是應用邏輯中的入口函式。

函式的呼叫過程要為函式開闢棧空間,用於函式的呼叫中臨時變數的儲存、現場保護。我們把這塊空間成為

函式棧幀

我們需要了解一些暫存器:

ebp暫存器:基址暫存器,存放了函式棧幀

棧底的位址

esp暫存器:棧頂暫存器,存放了函式棧幀

棧頂的位址 s:static

eip(pc、ip):程式計數器,程式計數器裡儲存的內容永遠是當前正在執行指令的

(永遠指向下一條指令)

eax暫存器:利用eax進行函式的返回

對main()函式進行反彙編,反彙編**如下:

int main()

0022149a pop edi //出棧

0022149b pop esi //出棧

0022149c pop ebx //出棧,使esp向下移動

0022149d mov esp,ebp //將ebp賦值給esp

0022149f pop ebp //出棧,將出棧的內容儲存到ebp回到main函式的棧幀

002214a0 ret //ret指令會使得出棧一次,並將出棧的內容當做位址,將程式執行跳轉至此處

繼續執行會跳轉至main函式中:

總結

在最後,總結一下上述過程中出現過的彙編指令及其作用:

1.call:

通過修改ip實現函式的跳轉()

從右往左壓棧。

2. pop:出棧

eg:pop ebp 出棧至ebp

3.ret:調棧,棧頂回退,從myfunction回退到main。彈出棧頂返回值,將彈出的棧頂返回值存到eip

假如存入a,b,c,d,e

則在a的上面是b,c,d,e

a的下面是返回值的位址

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

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

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

1.cpu中的暫存器 通用暫存器 eax,ebx,ecx,edx 程式計數器 eip pc 存放當前正在執行的指令的下一條指令的位址。棧頂 esp暫存器 棧底 ebp暫存器 2.將記憶體中的指令複製到cpu中 讀取指令 分析指令 執行指令 3.什麼是棧?棧是一種特殊的鍊錶形式的資料結構,只允許在鍊錶...

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

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