什么是棧幀


棧幀

那先有個問題,什么是棧?

在數據結構中, 棧是限定僅在表尾進行插入或刪除操作的線性表。棧是一種數據結構,它按照后進先出的原則存儲數據,先進入的數據被壓入棧底,最后的數據在棧頂,需要讀數據的時候從棧頂開始彈出數據。
在計算機系統中,棧也可以稱之為棧內存是一個具有動態內存區域,存儲函數內部(包括main函數)的局部變量和方法調用和函數參數值,是由系統自動分配的,一般速度較快;存儲地址是連續且存在有限棧容量,會出現溢出現象程序可以將數據壓入棧中,也可以將數據從棧頂彈出。壓棧操作使得棧增大,而彈出操作使棧減小。
棧用於維護函數調用的上下文,離開了棧函數調用就沒法實現。

而什么是棧幀(Stack Frame)呢?
每一次函數的調用,都會在調用棧(call stack)上維護一個獨立的棧幀(stack frame).每個獨立的棧幀一般包括:

  • 函數的返回地址和參數
  • 臨時變量: 包括函數的非靜態局部變量以及編譯器自動生成的其他臨時變量
  • 函數調用的上下文
    棧是從高地址向低地址延伸,一個函數的棧幀用ebp 和 esp 這兩個寄存器來划定范圍.ebp 指向當前的棧幀的底部,esp 始終指向棧幀的頂部;</br>
    ebp 寄存器又被稱為幀指針(Frame Pointer);</br>
    esp 寄存器又被稱為棧指針(Stack Pointer);
 
image

 

在函數調用的過程中,有函數的調用者(caller)和被調用的函數(callee).
調用者需要知道被調用者函數返回值;
被調用者需要知道傳入的參數和返回的地址;

函數調用

函數調用分為以下幾步:

  • 參數入棧: 將參數按照調用約定(C 是從右向左)依次壓入系統棧中;
  • 返回地址入棧: 將當前代碼區調用指令的下一條指令地址壓入棧中,供函數返回時繼續執行;
  • 代碼跳轉: 處理器將代碼區跳轉到被調用函數的入口處;
  • 棧幀調整: </br>
    1.將調用者的ebp壓棧處理,保存指向棧底的ebp的地址(方便函數返回之后的現場恢復),此時esp指向新的棧頂位置; push ebp </br>
    2.將當前棧幀切換到新棧幀(將eps值裝入ebp,更新棧幀底部), 這時ebp指向棧頂,而此時棧頂就是old ebp mov ebp, esp </br>
    3.給新棧幀分配空間 sub esp, XXX</br>

函數返回

函數返回分為以下幾步:

  • 保存被調用函數的返回值到 eax 寄存器中 mov eax, xxx
  • 恢復 esp 同時回收局部變量空間 mov ebp, esp
  • 將上一個棧幀底部位置恢復到 ebp pop ebp
  • 彈出當前棧頂元素,從棧中取到返回地址,並跳轉到該位置 ret


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM