程序的位址空間與函式呼叫過程

2021-07-11 02:42:01 字數 2606 閱讀 5973

要知道c語言的函式呼叫過程,首先要明白c語言中的各部分**都出現在什麼段。

首先來看一串**,**中的各個部分都有自己對應的段,換句話說每個段都存有c語言中的各個部分**,而這所有的**組合起來才成為乙個完整的c語言**。只有在知道c語言各部分**出現在什麼段之後,就可以進一步了解c語言中的函式呼叫過程。(該程式是在linux中建立)

當然在知道c語言中的各個部分對應的段之後,我們就可以研究一下c語言中的函式呼叫過程。但在這之前,有乙個知識還是必須知道,那就是當我們程式執行起來之後,可執行檔案載入到記憶體之後如何分布。還是以剛剛的a.out為例。

知道了以上內容之後,下面我們就可以開始核心內容了,函式的呼叫原理--棧幀

我們都知道棧是c語言中的乙個很重要的內容,首先棧是向下生長的,所謂向下生長是指從記憶體高位址->低位址的路徑延伸,所以我們就得到兩個很重要的東西,就是棧有棧底和棧頂,由於棧的特性,棧頂的位址要比棧底的低。對於×86體系的cpu而言,其中

------>暫存器ebp(base pointer)可稱為「幀指標」或「基址指標」,兩者的語義是相同的。

------>暫存器esp(base pointer)可稱為「棧指標」。

要知道的是:

------->ebp在未接受改變之前是一直指向棧幀的開始,也就是棧底,所以ebp的用途是在堆疊中定址用的。

------->esp是會隨著資料的入棧和出棧移動的,也就是說,esp始終指向棧頂。

我們**結合簡單說明一下:假設函式a呼叫函式b,我們稱a函式為「呼叫者」,b函式為「被呼叫者」則函式呼叫過程可以簡單的描述:

(1)先將呼叫者(a)的堆疊的基址(ebp)入棧,以儲存之前的任務資訊。

(2)然後將呼叫者(a)的棧頂指標(esp)的值賦給ebp,作為新的基址(即被呼叫的棧底)。

(3)然後在這個基址(被呼叫者b的棧底)上開闢(一般用sub指令)相應的空間用作呼叫者b的棧空間。

(4)函式b返回之後,從當前棧幀的ebp即恢復為呼叫者a的棧頂(esp),使棧頂恢復函式b被呼叫前的位置,然後呼叫者a再從棧頂可彈出之前的ebp值(可以這麼做是因為這個值在函式呼叫前一步被壓入堆疊)。這樣,ebp和esp就都恢復了呼叫函式b之前的位置,也就是棧恢復函式b呼叫前的狀態。

這個過程由以下兩條指令來完成:

move  %ebp , %esp

pop   %ebp

這個過程用圖簡單的可以表示為:

下面以乙個簡單的函式為例子,add()函式,實現兩個數的相加,源程式很簡單。

#includeint add(int num1, int num2)

int main()

我們就用這個例子來簡單說一說c語言中的函式呼叫過程。首先我們必須要知道我們經常用的main()函式,實際上也是呼叫的,main()函式是被__maincrtstarup(或者說是__tmiancrtstarup)呼叫。知道這個之後我們就用圖來表示:

由於我們的main()函式是被其他函式呼叫的,所以在這之前棧指標esp和幀指標ebp最初都是如圖所示的樣子,但是在去呼叫main()函式之前,esp指標會向上移動,空出來的這個空間放什麼呢?這個後面會提到。接著進入main()函式。我們看main()函式的彙編**:(為了方便直接把圖放在組合語言中)

00a8149a pop ebx //指標撤回,銷毀內容,每次都有

00a8149b add esp,0e4h //main()函式的銷毀

00a814a1 cmp ebp,esp //編譯器在這裡做的乙個esp的檢測

00a814a3 call __rtc_checkesp (0a8113bh) //呼叫指令,到這裡main()函式的呼叫基本結束了

00a814a8 mov esp,ebp //ebp賦值給esp

00a814aa pop ebp //ebp出棧

最後銷毀:main()函式即可。

總結起來函式呼叫過程其實挺複雜的,若是乙個複雜的程式會更加複雜。這裡只是用乙個簡單的程式簡單分析一下。其實具體更深的內容還得自己多去除錯。

程序的線性位址空間以及函式呼叫過程

函式棧幀向低位址延伸。堆由低位址向高位址延伸。ebp以前的棧的基位址。通過乙個很長的區域性變數,將返回位址給覆蓋。esp 棧頂指標,隨著資料入棧出棧發生變化。esp減少代表分配棧空間,esp增加,代表棧空間減少。ebp 基位址指標,用於標示棧中乙個相對穩定的位置,用於引用函式引數以及區域性變數。計算...

函式呼叫過程

每乙個未執行完的函式都對應著乙個棧幀,系統為單個函式分配的那部分棧空間就叫做棧幀,棧幀儲存了函式的資訊。以下面的 為例,通過彙編 的執行過程介紹棧幀建立和銷毀的過程 include int add int x,int y int main 從main函式建立自己的棧幀開始 其他內容先忽略 初始狀態 ...

函式呼叫過程

c語言種有三種迴圈 do.while while for 初始化 條件判斷 步進 主函式 main 庫函式自定義函式函式的發明,使得變成可以以函式為單位進行模組化,叫做面向過程。軟體工程中,有 高內聚,低耦合 的要求。函式就是為了實現以上要求發明的產物。函式是面向過程的 介面 其介面包含了 引數 返...