該系列文章是依據本人平時對
反彙編的學習,歸納總結,所做的學習筆記。如有錯誤或待改善之處,請留下您寶貴的意見或建議。
棧幀也叫過程活動記錄,是編譯器用來實現過程
/函式呼叫的一種資料結構。棧幀是在程式的執行時棧中分配記憶體塊,專門用於特定的函式呼叫。
當乙個函式沒有執行時,它可能並不需要記憶體;但是當乙個函式被執行後,它就可能因為某種原因需要用到記憶體。原因有:
1.函式的呼叫方可能希望以引數(實參)的方式向該函式內傳遞資訊,這些引數需要儲存在函式能夠找得到他們的地方。
2.在執行任務的過程中,函式可能需要臨時的儲存空間。程式設計師通常會通過宣告區域性變數來分配這類臨時空間,這些變數將只在函式內部使用,函式執行結束後,將被銷毀,不能在訪問他們。
編譯器通過棧幀(也叫做啟用記錄)使得對函式引數和區域性變數進行分配和釋放的過程對程式設計師透明。在將控制權交給函式之前,編譯器會插入**,將函式引數放入棧幀內,並分配足夠的記憶體,以儲存函式的區域性變數。鑑於棧幀的結構,函式的返回位址也被儲存在新的棧幀中。使用棧幀使得使用遞迴成為可能,因為每個遞迴函式呼叫都有它自己的棧幀,這恰好將當前的呼叫和之前的呼叫分隔開來。下面是
呼叫乙個函式的詳細過程:
1.
呼叫方將呼叫函式所需的任何引數放入該函式所採用的呼叫約定指定的位置。如果引數被放入執行時棧上,該操作可能引起程式棧指標的變化。
2.
呼叫方將控制權交給被呼叫函式,這個過程有
x86 call
或mips jal
等指令實現。然後返回位址被儲存到程式棧或暫存器中。
3.
如果必要,被呼叫函式會配置乙個棧指標,並儲存呼叫方希望保持不變的任何暫存器值。
4.
被呼叫的函式為它可能需要的任何區域性變數分配空間。一般,通過呼叫程式棧指標在執行時棧上保留空間來實現。
5.
被呼叫函式執行其操作,可能產生乙個結果。在執行操作過程中,被呼叫函式可能會訪問呼叫函式傳遞過來的引數,如果函式返回乙個結果,此結果通常被放在乙個特定的暫存器中,或者放置在函式返回後呼叫方可立即訪問的暫存器中。
6.
函式完成其操作後,任何存放區域性變數的棧空間將被釋放。通常,逆向執行第
4步的操作即可完成相應的工作。
7.
如果某個暫存器的值還為呼叫方儲存(第
3步)著,那麼將其恢復到原始值。這包括恢復呼叫方的棧指標暫存器的值。
8.
被呼叫的函式將控制權返回給呼叫方。實現這一步的主要指令包括
x86 ret
和mips jr
。根據所使用的呼叫約定,這一操作可能會從程式棧中清除乙個或多個引數。
9.
呼叫方一旦重新獲得控制權,它可能需啊喲刪除程式棧中的引數。這時,可能需啊喲對程式棧進行調整,將程式棧指標恢復到第一步之前的值。 第
3步和第
4步通常在進入函式時執行,它們共同稱為函式的序言。同樣,第
6步到第
8步一般在函式結束時執行,它們共同稱為函式的尾聲,而第
5步則代表函式的主體,它們是呼叫函式時執行的全部操作。
函式呼叫過程(棧幀)
眾所周知,程式每呼叫乙個函式,系統都會為其開闢一塊空間,當它返回時,才收回這塊空間。程式崩潰有一部分原因就是因為無限制的呼叫函式,卻沒有及時返回,導致記憶體空間不夠。為了更好的維護這一塊空間 通常稱為棧空間 我們需要了解兩個暫存器,乙個為 esp 指向棧頂的指標 乙個為 ebp 指向棧底的指標 棧空...
函式棧幀(呼叫過程)
函式棧幀就是在呼叫函式是為其在棧空間上開闢了一段空間,指向過程呼叫,乙個過程呼叫包括將資料 以過程引數和返回值的形式 和控制從 的一部分傳遞到另一部分。我們以以下 為例講解整個函式呼叫過程 int my add int x,int y int main 一 呼叫main 函式 我們從main 函式的...
C語言 函式呼叫過程(棧幀)
首先舉個栗子 include int add int x,int y int main 在這個程式裡,函式被呼叫才會發揮函式的功能,而函式的呼叫其實是乙個過程,在這個過程計算機要為函式開闢棧空間,用於本次函式臨時變數的儲存和現場保護,這塊空間稱為函式的棧幀。現場保護的作用是為了在呼叫完另乙個函式,返...