2014-02-12 81 views
3

我發現ESP寄存器是當前堆棧指針,EBP是當前堆棧幀的基址指針。但是,我不明白這些定義(我剛開始學習如何在彙編中編寫代碼)。什麼是ESP和EBP寄存器?

我的理解是ESP指向堆棧本身,EBP指向堆棧頂部的任何東西。但這些只是我的猜測,他們很可能是不正確的。否則,像下面這樣的陳述意味着什麼?

MOV EBP, ESP  

編輯:我認爲上面的聲明是我的書的錯字。我認爲它應該是EBX而不是EBP

+0

EBX和EBP是不同的寄存器。 –

回答

6

esp是堆棧指針,ebp是/爲一個堆棧幀,所以當你輸入一個函數時,ebp可以得到一個esp的副本,在這之前堆棧上的所有東西都會發生,返回地址,傳入參數等等,對於該函數來說全局的東西(局部變量)現在將在函數的持續時間內遠離堆棧幀指針的靜態距離。 esp現在可以隨意編譯,並且可以在嵌套到其他函數時使用(每個函數都需要自然保留ebp)。

這是一種懶惰的方式來管理堆棧。使編譯器調試更容易,使得編譯器生成的代碼更容易理解,但會燒燬可能是其他通用目的的寄存器。

2

正常情況下,EBP用於備份ESP,因此如果通過函數中的代碼更改ESP,則恢復ESP所需的全部內容爲mov ESP,EBP。另外,由於EBP通常不受函數中的代碼的影響,因此可用於訪問傳遞的參數或局部變量,而無需調整偏移量。

對於「堆棧幀」的用法,EBP在任何函數啓動時被壓入堆棧,所以EBP推入堆棧的值是來自調用當前函數的函數的EBP值。這使得代碼或調試器可以通過EBP被壓入堆棧的所有實例「回溯」,並且堆棧上的EBP值的每個實例可以被認爲是堆棧幀的基指針。

請注意,某些編譯器具有「省略幀指針」選項,在這種情況下EBP不用於保存ESP或作爲堆棧幀指針。相反,編譯器會跟蹤ESP,並且所有本地偏移量均與ESP的當前值有偏差。

2

EBP和ESP是時代的殘餘,編譯器沒有例如有靜態分析來檢測函數調用中需要多少個字節的堆棧。另外,堆棧應該在函數執行過程中動態增長和縮小,中斷將允許將所有堆棧從0清除到SP,而意大利麪條代碼是事實上的標準。實際上,中斷(以及僅通過寄存器傳遞參數)是調用內核函數的設計方法。

在這些環境中,一個需要有一個棧的固定點,其中總是找到調用者的返回地址,局部變量和函數的參數。因此bp註冊是合理的。在這個架構bp被允許被索引([bp-300h]),但是sp不是。那些可能被解釋爲mov ax, [sp + 1111h]的操作碼/指令編碼被重新用於其他目的。

在386+中,通過引入'E',ESP獲得了偏移量的屬性。此時EBP已經從唯一目的中解脫出來,因​​爲esp能夠處理這兩項任務。

請注意,即使現​​在EBP指向內存通過堆棧,就像ESP。 EBX和BX使用DS。

+0

我發現你的回答非常豐富,但我不確定你最後一句話的含義:「EBX和BX使用DS。」? –

+1

歷史上,IA具有段寄存器;代碼爲CS,數據爲DS/ES,堆棧爲SS。每個段一次只能訪問64kb的內存。 386具有相同的架構,增加了FS和GS,但現在每個段可以配置爲訪問1字節到4GB內存之間的任何地方。每個指令或尋址模式都有一個隱式段寄存器,通過它來訪問存儲器。甚至後來的「扁平」內存模型也成爲事實上的標準,每個段寄存器都可以看到所有內容(但內核,它保留了例如GS寄存器)。 –

相關問題