2012-08-23 62 views
4

我剛學完ARM架構/程序集。如果SP寄存器保存下一個存儲位置的地址來存放數據,那麼堆的地址是什麼?例如,在C++中,如果你在堆上聲明一個對象(例如MyObj example = new MyObj();),那麼程序集看起來會是什麼樣子,從哪裏知道example是哪裏?什麼寄存器指向堆?

+0

這是編譯器的實現細節。 http://www.blackhat.com/presentations/bh-usa-07/Ferguson/Whitepaper/bh-usa-07-ferguson-WP.pdf –

+0

寄存器是CPU需要知道的事情。有一個SP寄存器,因爲CPU有特殊的硬件,可以自動執行堆棧操作(例如,發生中斷時保存上下文)。 CPU不知道或關心堆。 – TJD

+0

堆不是硬件的東西,堆棧是。 heap和堆內的分配與語言和庫有關(與硬件無關)。 –

回答

5

在此上下文中的堆棧是由OS/EABI提供的較低級別的結構。這就是爲什麼有一個傳統的註冊表。但是,堆是OS提供的更高層次的結構。因此,管理和使用它取決於與您的應用程序和操作系統的協議。在彙編術語中,您將使用該堆通過寄存器取消引用一些地址。

+1

好,所以你說的CPU級別沒有真正的堆概念? – Celeritas

+0

是的,就是這樣。任何你正在玩(讀/寫)的內存都必須允許你這麼做。這是操作系統的幫助,你可以通過malloc分配一些內存,或者你的應用程序已經告訴操作系統在可執行二進制文件中需要多少內存。然後,當您使用該內存時,您將開始取消引用包含您可以使用的區域地址的寄存器。 – auselen

+0

在ARM上,也沒有像堆棧的真正硬件支持。在這方面,它與x86非常不同。 CPU本身並不知道「堆棧」是什麼。而且你還需要操作系統支持堆棧區域,因爲如果需要的話,內核必須增加你的堆棧。 –

5

SP寄存器通常用於跟蹤堆棧中的當前位置。這意味着它總是需要指向堆棧。

同樣不能說堆。當您需要訪問變量時,該變量的地址將存儲在您的應用的指針或其他內存引用中。在需要地址的時候,可以使用寄存器來做參考。但是哪個寄存器的細節不僅依賴於編譯器,而且還可能取決於在從相同編譯器優化代碼之後哪個寄存器可用。

+0

想想看,爲什麼註冊15(或者其他任何適用於ARM)的SP?爲什麼不登記?這是多快? – Celeritas

+0

爲什麼不是SP?堆棧需要一個受呼叫和返回影響的專用寄存器,該寄存器是SP。 –

+0

但是有什麼區別。你需要一個專用的堆棧寄存器,但不是堆? – Celeritas

0

在ARM的EABI中,R13(SP)指向完全遞減堆棧中的最後推送數據。然而,沒有必要指出,在任何時候,這樣的代碼可以是合法的:

考慮到r0指向我們的程序可訪問的有效內存位置。

stmfd r0!, {r1-r12, sp, lr} 
ldr r1, [r0] 
mov r2, lr 
sub lr, sp, #4 
str sp, [r4] 
add sp, lr, #4 
ldmfd r0!, {r1-r12, sp, pc} 

ofcourse它沒有任何意義,但它是唯一的一點是,如果你可以安全地重新加載SP,LR和其他所有被調用函數保存的寄存器,你可以從頭開始他們多,你想一邊回憶恢復他們的價值在返回給調用者之前。另一點,堆棧和堆可能不一定相同,堆是malloc/free類型構造的更高級別的抽象,而堆棧僅用於在4個寄存器不足或用於傳遞函數參數時保存被調用寄存器,數據結構和所有你可以想象的,但堆棧有點難以管理,因爲你必須自己跟蹤所有的數據,而不是僅僅將一個區域分配給一個指針,然後在完成後釋放它。

通常取決於程序和環境,您可以使用各種黑客和東西的優化技術,如明知腐敗的一些非暫存寄存器,並擺脫它,但是你必須要管理,在您的來電顯示功能,它應該是意識到在隨後的函數調用中會被劃傷的寄存器,因此EABI只有在將控制轉移到另一個程序或接管時纔有意義,您可以在CPU上執行您喜歡的任何操作,只需確保將其保留爲乾淨它是在你進入這個地方之前。

1

處理器需要一個特殊的堆棧指針寄存器,因爲有時(中斷或異常)處理器硬件必須直接修改SP,而不執行任何代碼。這對堆沒有必要,所以不需要使用特殊寄存器來指向堆。在運行時,操作系統決定特定的代碼塊在堆中的存儲位置,並且可以使用任何寄存器來保存該地址。