乙個完整的能實現一些基本功能的程式總要或多或少的呼叫一些函式,但函式的具體呼叫過程是怎樣的,從列印出來的結果來看,顯然是無法得知的,這就需要對函式的呼叫過程有乙個深入地研究。
從簡單的**開始:
#include
intadd
(int x,
int y)
intmain()
進行程式除錯,檢視【呼叫堆疊】,如下:
可以看到在main
函式執行前,先執行的是__tmaincrtstartup
函式和maincrtstartup
函式,執行過程是在maincrtstartup
函式中呼叫__maincrtstartup
函式,在_maincrtstartup
函式中呼叫main
函式。每一次函式呼叫都是乙個過程,而這個過程叫做函式的呼叫過程,這個過程要為函式開闢棧空間,用於本次函式呼叫中臨時變數的儲存、現場保護。這塊棧空間稱為函式棧幀。
在函式棧幀的維護中有兩個很重要的暫存器,分別是esp(extend stack pointer)
和ebp(extend base pointer)
,它們分別指向棧幀的棧頂的位址和棧底的位址。如圖:
如果想要深入了解函式的呼叫過程,需要轉到彙編**。
首先我們來看main
函式的棧幀的建立:
add
函式的呼叫:
執行call
指令,f11後:
再按一次f11,進入add
函式內部,開始執行add
函式:
接下來是呼叫結束,返回值的部分(按照之前壓棧的相反順序出棧):
以上對整個壓棧過程分析,如下圖:
在了解了以上過程後,對任何乙個程式,都可以知道它的執行過程,例如下面這段**(但此**只可以在vc++6.0環境下執行):
#include
void
fun(
)int
main()
執行結果如下:
由於上面有對main
函式的棧幀建立,接下來直接來看對fun
函式的呼叫:
在函式棧幀建立及使用中,需要注意以下幾點:1、棧幀的使用是先使用高位址然後使用低位址;
2、引數的傳遞從右向左傳遞。
3、在整個程式的棧幀建立過程中,始終只有一組esp和ebp,只不過這兩個暫存器都是動態的,一直在移動。
函式呼叫過程(棧幀)
眾所周知,程式每呼叫乙個函式,系統都會為其開闢一塊空間,當它返回時,才收回這塊空間。程式崩潰有一部分原因就是因為無限制的呼叫函式,卻沒有及時返回,導致記憶體空間不夠。為了更好的維護這一塊空間 通常稱為棧空間 我們需要了解兩個暫存器,乙個為 esp 指向棧頂的指標 乙個為 ebp 指向棧底的指標 棧空...
函式棧幀(呼叫過程)
函式棧幀就是在呼叫函式是為其在棧空間上開闢了一段空間,指向過程呼叫,乙個過程呼叫包括將資料 以過程引數和返回值的形式 和控制從 的一部分傳遞到另一部分。我們以以下 為例講解整個函式呼叫過程 int my add int x,int y int main 一 呼叫main 函式 我們從main 函式的...
函式的呼叫過程 棧幀
在談棧幀之前,我們必須要先知道c c 程式記憶體的分配情況。乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 1 棧區 stack 由編譯器自動分配釋放 存放為執行函式而分配的局 部變數 函式引數 返回資料 返回位址等。其操作方式類似於資料結構中的 棧。2 堆區 heap 一般由程式設計師分配釋...