在學習C語言時,我們難免有許多疑問
例如:
(1)區域變數是怎么創建的?
(2)為什么區域變數的值是隨機的?
(3)函式是怎么傳參的?傳參的順序如何?
(4)形參和實參是什么關系?
(5)函式呼叫是怎么做的?
(6)函式呼叫結束后是怎么回傳的?
這些疑問其實都和函式堆疊幀的創建與銷毀有關
暫存器
eax,ebx,ecx,edx,ebp,esp等都屬于暫存器
ebp與esp 這兩個暫存器放的是地址,這兩個地址用來維護函式堆疊幀的,每一次函式呼叫都要在堆疊區上開辟一塊空間

在VS2013中main函式被__tmainCRTStartup所呼叫

以下面代碼做為研究:
#include<stdio.h>
int Add(int x, int y) {
return x + y;
}
int main() {
int a = 10;
int b = 20;
int c = Add(a, b);
printf("%d", c);
return 0;
}
按f10進入除錯,右鍵進入反匯編

如下圖:(如果顯示的是符號,可以右鍵將符號去掉)


接著我們開始逐條執行,此時ebp和esp分別存放兩個地址

這兩個暫存器存的地址便是__tmainCRTStartup函式所壓的堆疊

隨著代碼的執行,esp會指向ebp所存地址

此時esp進行減法

地址變化如下:

相當于為main函式預開辟一段空間,執行如下圖所示:


接下來的三步push相當于壓了三次堆疊


接下來幾步相當于將main函式中全部初始化為CCCCCCCC

然后接著執行

這步的意思是將a放在ebp-8的位置

此處即是為a開辟的空間,所以當a未初始化時,a放的便是CCCCCCCC,所以為隨機值

創建的a和b在記憶體中便如上圖一樣存放
接著,代碼呼叫Add函式

此時,我們可以觀察到,用eax來存ebp-14h以及用ecx來存ebp-8的地址,而ebp-14h和ebp-8分別是b和a的地址

呼叫之后壓堆疊如上圖
執行到call這步后,按f11進入所呼叫函式內部

函式內部如下

然后我們可以觀察到,呼叫的Add函式前半部分和main函式的初始化一樣,為Add函式的準備作業,而第一條陳述句的push相當于將原來壓在main函式的ebp壓在Add上

接下來幾條陳述句便是Add函式的堆疊幀

執行完前面陳述句后,x,y呢?

這兩條陳述句我們看到,在需要x和y時,我們找到了ebp+8和ebp+0Ch

而此時ebp+8和ebp+0Ch恰好表示ecx和eax,即存放的a和b,所以形參不是在Add函式內部創建的,而是在暫存器中找的
函式的傳參是在函式創建之前就已經壓堆疊了,所以我們說形參是實參的一份臨時拷貝,所以改變形參并不會影響實參

當函式執行到此處時,彈出edi,esi和ebx,然后將ebp地址賦給esp,即銷毀掉Add函式
熱門文章:
AI三子棋,極大極小值演算法
掃雷游戲
DP動態規劃
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/293651.html
標籤:其他
