2013-06-21 62 views
4

在我看到的大部分x86程序集(特別是NASM)代碼示例中(甚至在GCC生成的代碼示例中),我看到了「堆棧幀的設置」。就像這樣:x86彙編:爲什麼我需要堆棧框架?

main: 
     /*setting the stack frame*/ 
     push ebp  
     mov  ebp,esp 

     ... 
     code goes here 
     ... 

     /*removing the stack frame*/ 
     mov  esp, ebp 
     pop  ebp 

我對這種做法3個問題:

  1. 如果我的代碼沒有接觸到紙堆,然後設置/移除棧幀如上面是完全沒用的,對不對?

  2. 即使我的代碼使用堆棧,只要彈出我推送的所有東西(離開堆棧,因爲它本質上),然後再次設置堆棧幀是完全沒用的,對吧?

  3. 正如我所看到的,這樣做的唯一目的是保存ESP的價值,這樣我就可以在我的代碼上玩弄它而不用擔心搞砸了,一旦完成,我只需恢復其原始值。這是堆棧框架設置的目的還是我錯過了什麼?

感謝

+0

如果要調試程序並查看堆棧跟蹤,則堆棧框架也是必需的。 – ctn

+0

堆棧幀並不是真的需要。如你看到的。在X86-64中,我們沒有堆棧幀和ebp寄存器。所以你是對的,堆棧框架只是爲了方便使用。 – baotiao

回答

5

那麼,事實上,你不需要堆棧幀。

當您保存寄存器並將本地變量存儲在堆棧中時,堆棧框架非常方便 - 使寫入和調試更加容易:只需將ebp設置爲堆棧中的固定點,並使用ebp來定址所有堆棧數據。最後恢復esp更容易。另外,調試器經常期望堆棧幀出現,否則你可能會得到不準確的堆棧調用。

因此,對1的回答是肯定的,對2和3的回答在上面。

2

你基本上是正確的。

即使您不需要固定堆棧引用來訪問參數和本地文件,堆棧框架也具有一定的優勢。特別是讓它們在那裏允許精確的堆棧走動來生成用於調試目的的堆棧軌跡。

2

這是按慣例完成的。 C語言函數使用堆棧幀來訪問發送給函數的參數,並設置動態局部變量。這就是爲什麼他們在你正在看的示例代碼中執行它。當然,如果你想按照你的方式做,你可以,但是你將無法從C等調用你的代碼。

編輯:我也很確定有編譯器實現不同的調用約定,優化,也許根本不創建框架。所以基本上,你是對的。堆棧幀不是必需的。

+0

參數實際上與當前堆棧幀的基底處於負偏移。 –

+0

是的。我沒有說他們在框架內。 – akonsu

+0

它使用堆棧將參數傳遞給函數,但如果我正確記得它,它不會指定使用堆棧幀。實際上,函數調用約定根本不依賴於堆棧幀。 – Inspired