因為實驗室專案的原因,才開始接觸powerpc,錯誤的地方還望看到的各位指正。
上面就是ibm的手冊上面畫的棧幀,他的文字描述也符合這個示意圖,理解起來就是棧頂存放的是上乙個棧的棧頂的位址。r1暫存器(一般作為預設的堆疊指標)存放自身的棧頂。因為沒有push和pop指令,所以是通過stwu和lwzu來進行push和pop的。下面假設呼叫函式為main(),被呼叫函式為func()。根據手冊上來說:
從棧底到棧頂依次存放的是
(1)函式引數域fpr(function parameter register):這個區域的大小是變化的,當呼叫者傳遞給被呼叫者的引數少於8個時,用gpr3-gpr10這8個暫存器就行,被呼叫者的棧幀中就可不要這個區域;但如果傳遞的引數多於8個時就需要這個區域。
(2)通用暫存器gpr(general parameter register):當需要儲存gpr暫存器中的乙個暫存器gprx時,就需要把從gprx-gpr31的值都儲存到堆疊幀中。
(3)cr暫存器:即使修改了cr暫存器的某乙個段crx(x=0至7),都要儲存這個cr暫存器的內容。
(4)區域性變數域(local variables area):同上fpr所示,如果臨時暫存器的數量不足以提供給被呼叫者的臨時變數使用時,就會使用這個區域。
(5)function parameters:跟第乙個fpr重複了?暫時不知。
(6)padding:是補齊位元組數,讓當前棧幀的長度保持8bytes的倍數。
(7)lr鏈結暫存器(link register):也就是被呼叫函式的返回位址,main函式中呼叫func函式的那條指令的下一條指令的位址
。(8)back chain word:
即上乙個棧幀的低位址,也是r1存放的位址值,可以把這個作為基址進行自己棧幀內的定址
。呼叫的過程舉例如下:
func中開始幾行彙編會為自己建立棧幀:
func的結尾幾行,會移除前面建立的棧幀,並使得sp(即gpr1)暫存器指向上乙個棧幀的棧頂(即棧幀的最低位址處,也就是back chair)
如下所示:
用圖例來講就是:
不過有個很奇怪的地方,按照ibm的示例**,如果是先stwu %r1,-88(%r1);再stw %r0,+92(%r1),也就是儲存在棧上的位置加的比棧分配的空間大(分配了88位元組,存放的位置是+92),那儲存的lr不是變成了在上乙個棧幀的內部了麼?這個不就跟ibm的棧幀的示意圖衝突了麼(棧幀示意圖中的lr存在的是被呼叫函式自己的棧內,文字描述也是這個意思)?按**儲存的lr應該是儲存在main函式還未呼叫func時r1+4的位置,示例如下,為了區別,呼叫func時的r1寫成r』:
我去找了人家的反匯程式設計序看了看:
可以看到,在main函式的跳轉的時候用的bl,bl跳轉的時候可以存放lr,因為func什麼也沒有,所以編譯器自動把儲存lr到棧的部分忽略了,可能是編譯器優化的結果?在上圖中,func存放呼叫函式棧頂的方法是用的r31這個暫存器,但是在之前先儲存了原先r31的值,而且是在自己的棧內。在main函式裡面我們可以看到ibm手冊裡面說的那種建立棧幀的標準方法,但是存lr還是超過了分配給自己的棧大小(分配了16,存的位置是20(r1))。這個我也不知道是為什麼存lr要儲存到上乙個棧,這跟棧幀示意圖裡面lr儲存的位置不同,只能以後看能不能問到更多的牛人的意見了……
IDA棧幀相關理解
原始碼 基於esp 的棧幀 基於ebp 的棧幀 call 函式呼叫指令 格式 call oprd 功能 過程呼叫指令 1.其中oprd為過程的目的位址.2.過程呼叫可分為段內呼叫和段間呼叫兩種.定址方式也 可以分為直接定址和間接定址兩種.3.本指令不影響標誌位.近呼叫 呼叫當前 段 cs 暫存器當前...
深入理解C 函式棧幀
目錄 每一次函式呼叫都是乙個過程,為函式開闢棧空間,用於本次函式呼叫中臨時gyoosgl變數的儲存 現場保護。這塊棧空間我們稱為函式棧幀。棧是從高位址向低位址延伸的。暫存器ebp指向當前的棧幀的底部 高位址 暫存器esp指向當前的棧幀的頂部 低位址 注 esp 棧指標暫存器 extended sta...
程式棧 棧幀
乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 棧區 stack 由編譯器自動分配釋放 存放函式的引數名,區域性變數的名等。其操作方式類似於資料結構中的棧。堆區 heap 由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os 注意它與資料結構中的堆是兩回事,分配方式倒是類似於鍊錶。靜...