過程呼叫約定

2021-04-29 00:54:32 字數 1862 閱讀 8157

過程呼叫約定

當程式中的各個過程(函式)被分別編譯時,關鍵是如何規定暫存器的使用規則。當編譯某個過程時,編譯器必須事先知道需要用到哪些暫存器、哪些暫存器的內容需要保留給其他過程使用等資訊。我們稱這些暫存器的使用規則為暫存器使用約定過程呼叫約定。顧名思義,大多數情況下,這些規定主要是用於約束軟體的,而不會受到硬體的限制。因此,大多數的編譯器和程式設計師都必須遵守這些約定以免發生錯誤。

下面是gcc編譯器在mips系統下的暫存器使用約定。

1、過程呼叫

下面說明乙個程式(呼叫者)呼叫另乙個程式(被呼叫者)的具體步驟。

大多數有關過程呼叫的記錄集中在乙個叫做過程呼叫幀(procedure call frame)的記憶體塊中。使用這塊記憶體區域有以下幾個目的:

a. 存放傳遞給被呼叫過程的引數值

b. 保留當前過程可以修改但給過程的呼叫者不希望改變的暫存器值(返回前必須恢復,亦即使用前必須儲存)

c. 為過程的區域性變數提供足夠的記憶體空間。

在大多數程式語言中,過程呼叫和返回嚴格遵從後進先出(lifo)原則,因此,這些記憶體可以在堆疊段實現分配和釋放,這也是為什麼這些記憶體塊有時被稱作堆疊幀。

下圖是乙個典型的堆疊幀。

幀的記憶體區域包括幀指標$fp(指向幀的首字)暫存器和堆疊指標$sp(指向幀的尾字)暫存器值之間的範圍。由於堆疊的儲存遵從由高到低的存放順序,所以幀指標總是高於堆疊指標。執行的程式利用幀指標能快速地訪問堆疊幀中的內容。例如,堆疊幀中的引數能夠用下面的指令送入暫存器$v0:

lw $v0, 0($fp)

堆疊幀能用多種途徑實現;但無論如何,呼叫者和被呼叫者必須遵從一系列步驟。下列描述的步驟用於大多數mips系統上的呼叫協議。在過程呼叫中,該協議在三個時刻發揮作用:在呼叫者呼叫被呼叫者之前,在被呼叫者開始執行的時刻,以及在被呼叫者返回到呼叫者之前的時刻。首先,呼叫者將過程呼叫引數放到合適的位置,然後按下列步驟呼叫目的過程:

1)傳遞引數。根據協議,前四個引數將被送到暫存器$a0~$a3中,其他引數壓到堆疊中,這些引數剛好放在被呼叫過程的堆疊幀的起始位址處(從而在被呼叫過程中通過堆疊幀暫存器$fp的值訪問這些引數),達到引數傳遞的目的。

2)儲存呼叫者的暫存器的值。這樣,被呼叫過程就可以隨意使用這些暫存器($a0~$a3,$t0~$t9),而無須先儲存它們的值。如果呼叫者在呼叫之後還想使用這些暫存器,那麼它必須在呼叫前儲存暫存器的值)。

3)執行jal指令。該指令把控制轉移到被呼叫者的第一條指令處,並且在暫存器$ra中儲存返回位址(而不是在ia-32系統中,將返回位址壓棧,遭受緩衝區溢位之攻擊)。

在被呼叫子程式正式執行之前(指執行子程式所代表之功能之前),該程式必須執行以下步步驟(例行公事),以便設定其堆疊幀:

1)通過從當前棧指標(暫存器)中減去棧幀之大小為棧幀分配空間(即$sp = $sp - framesize)。

2)把被呼叫者所用暫存器儲存到幀中。被呼叫者在改變其值之前必須儲存$s0~s7、$fp以及$ra的值,因為呼叫者希望呼叫之後暫存器沒有發生改變。而每個過程中如果需要建立新的棧幀則必須儲存$fp。而$ra則僅在被呼叫者再呼叫時才儲存。此外,其他被呼叫者專用的暫存器也要儲存。

3)設定棧幀指標,其值為棧幀大小減去4加上$sp,儲存在$fp中(即$fp=$sp+framesize - 4)。

最後,被呼叫者執行如下步驟,將控制返回給呼叫者:

1)如果被呼叫者為具有返回值的函式,則將返回值儲存到暫存器$v0中。

2)恢復被呼叫者進入時儲存的所有暫存器。

3)向$sp加上棧幀大小,將幀從棧中彈出($sp = $sp + framesize),釋放棧幀空間。

4)跳轉到$ra中記錄的制定位址處。

函式呼叫過程 棧幀 呼叫約定

考慮函式呼叫 func 1,2 需要把1和2這兩個引數進行傳遞,這裡的引數傳遞可以通過兩種方式 1.引數入棧 記憶體 2.引數傳遞到暫存器 大多數情況下,也是c c 的預設形式是通過棧進行傳遞,因為雖然暫存器傳遞方式快但是暫存器數量有限 引數壓入棧中 記憶體 cs ip指向下一條指令位址需要進行跳轉...

論調用約定

在c語言中,假設我們有這樣的乙個函式 int function int a,int b 呼叫時只要用result function 1,2 這樣的方式就可以使用這個函式。但是,當高階語言被編譯成計算機可以識別的機器碼時,有乙個問題就凸現出來 在cpu中,計算機沒有辦法知道乙個函式呼叫需要多少個 什麼...

函式呼叫約定

函式呼叫約定有多種,這裡簡單說一下 1 stdcall 呼叫約定相當於16位動態庫中經常使用的 pascal 呼叫約定。在32位的vc 5.0中pascal呼叫約定不再被支援 實際上它已被定義為 stdcall。除了 pascal外,fortran和 syscall也不被支援 取而代之的是 stdc...