1. 程式人生 > >函式呼叫與棧幀詳解

函式呼叫與棧幀詳解

函式呼叫與棧幀詳解

2017年04月19日 22:07:34 T_tangc 閱讀數:826

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/qq_25424545/article/details/70232141

 

            新手總結,若有誤,望牛人不吝賜教奮鬥

 

 

一、什麼是函式呼叫?什麼是棧楨?

我們知道每一次函式呼叫都是一個過程。這個過程我們通長稱之為:函式的呼叫過程。在這個過程要為函式開闢棧空間,用於本次函式的呼叫中臨時變數的儲存、現場保護。這塊棧空間我們稱之為函式棧幀。 如圖:

 

 

 

 

二、什麼是棧?

 

 在大學學習《資料結構》的時候,瞭解到棧作為一種特殊的資料結構而存在,是一種只能在一端進行插入和刪除操作的特殊線性表。

 它按照後進先出的原則儲存資料,先進入的資料被壓入棧底,最後的資料在棧頂,需要讀資料的時候從棧頂開始彈出資料(最後一個數據被第一個讀出來)。

棧有很多自己的特性,它具有記憶功能,對棧的插入與刪除操作中,不需要改變棧底指標;而且棧是從高地址向低地址延伸的。每個函式的每次呼叫,都有它自己獨立的一個棧幀,這個棧幀中維持著所需要的各種資訊。因此棧作用就是用來保持棧幀的活動記錄(即函式呼叫)。

 

 

三、函式呼叫和棧幀

 

在介紹具體呼叫過程之前先對相關的幾個名詞作一解釋。

1、ebp:棧底指標,即指向棧幀底部的指標。

2、esp:棧頂指標,棧幀指標只有一對。

3、call:用於儲存當前指令的下一條指令並跳轉到目標函式。

3、push:入棧(push   暫存器    保護資料)。

4、pop:出棧。

5、ptr:相當於指標

6、mov:類似於賦值操作。

7、add:加法操作。

8、sub:減法操作。

9、ecx :  是計數器(counter), 是重複(REP)字首指令和LOOP指令的內定計數器。

10、eax、是"累加器"(accumulator), 它是很多加法乘法指令的預設暫存器。

11、esi/edi分別叫做"源/目標索引暫存器"(source/destination index),因為在很多字串操作指令中, DS:ESI指向源串,而ES:EDI指向目標串.

12、ret:使得出棧一次,並將出棧的內容當作地址。將程式執行跳轉到該地址處。

注意!一定要要跟上思路,我們來看一個例子

 

 
  1. #include <stdio.h>

  2. int Add(int x, int y)

  3. {

  4. int z = 0;

  5. z = x + y;

  6. return z;

  7. }

  8. int main()

  9. {

  10. int a = 10;

  11. int b = 20;

  12. int ret = Add(a, b);

  13. printf("ret = %d\n", ret);

  14. return 0;

  15. }

1.從main函式的地方開始,要展開main函式的呼叫就得為main函式建立棧幀,那我們先來看main函式棧幀的建立。

2.Add函式的呼叫

 

3.Add函式裡

4、函式返回部分

 

 

到這裡整個函式呼叫過程完畢。

 

總結一下:棧幀其實是兩個指標暫存器,暫存器ebp為幀指標,而暫存器esp為棧指標,當程式執行時,棧指標可以移動(大多數的資訊的訪問都是通過幀指標的)。