函式呼叫與棧幀詳解
函式呼叫與棧幀詳解
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:使得出棧一次,並將出棧的內容當作地址。將程式執行跳轉到該地址處。
注意!一定要要跟上思路,我們來看一個例子
-
#include <stdio.h>
-
int Add(int x, int y)
-
{
-
int z = 0;
-
z = x + y;
-
return z;
-
}
-
int main()
-
{
-
int a = 10;
-
int b = 20;
-
int ret = Add(a, b);
-
printf("ret = %d\n", ret);
-
return 0;
-
}
1.從main函式的地方開始,要展開main函式的呼叫就得為main函式建立棧幀,那我們先來看main函式棧幀的建立。
2.Add函式的呼叫
3.Add函式裡
4、函式返回部分
到這裡整個函式呼叫過程完畢。
總結一下:棧幀其實是兩個指標暫存器,暫存器ebp為幀指標,而暫存器esp為棧指標,當程式執行時,棧指標可以移動(大多數的資訊的訪問都是通過幀指標的)。