我正在閱讀Richard Blum的專業彙編語言,我對本書中的不一致感到困惑,我想知道程序堆棧的增長方向究竟是什麼? 這是第312頁的圖片,它表明程序堆棧的增長。程序堆棧的增長方向究竟是什麼?
但是,當我達到322頁,我看到另一個版本,這表明程序堆棧向下增長。
這
我正在閱讀Richard Blum的專業彙編語言,我對本書中的不一致感到困惑,我想知道程序堆棧的增長方向究竟是什麼? 這是第312頁的圖片,它表明程序堆棧的增長。程序堆棧的增長方向究竟是什麼?
但是,當我達到322頁,我看到另一個版本,這表明程序堆棧向下增長。
這
該書不矛盾;每幅圖在頂部顯示更高的地址。
第一張圖說明了一個向下增長的堆棧。調用者將參數推入堆棧,然後調用新函數。調用行爲將返回地址壓入堆棧。被調用者然後將基指針的當前值推入堆棧,將堆棧指針複製到基指針中,並遞減堆棧指針以爲被調用者的局部變量騰出空間。
你是對的! – ssj
而在這種情況下,功能參數從右向左推; C這樣做是爲了支持具有可變數量參數的函數,如'printf'。 –
棧生長方向與操作系統,CPU架構,並且可能是一些其他的事情而改變。
最常見的佈局是堆棧從內存頂部開始並向下增長,而堆從底部開始並逐漸增長。有時候,這是另一種方式,例如。 OSX之前的MacOS將堆棧放在代碼區域的上方,成長起來,而堆棧則從內存頂部開始並逐漸減小。
一些背景資料:
對於不同的處理器的堆棧指針的含義和堆疊的方向可以不同。對於TMS Piccolo控制器堆棧正在成長,因此「PUSH」會增加堆棧指針。堆棧指針可指向上次推送的值或寫入下一個要推入的值的位置。 ARM處理器允許堆棧的所有4種可能的組合,所以必須有關於如何使用堆棧指針的約定。
在x86處理器:
在x86處理器堆棧始終向下生長所以「PUSH」指令將遞減堆棧指針;堆棧指針總是指向最後一個推送的值。
第一張圖顯示堆棧指針(地址>堆棧指針)後的地址已包含值。如果您將更多值存儲到堆棧中,它們將存儲到堆棧指針下方的位置(下一個值將存儲爲地址-16(%ebp))。這意味着頁面312的圖片也顯示了一個遞減的堆棧。
- 編輯 -
如果處理器有一個「PUSH」指令堆棧增長的方向是由CPU給出。對於沒有「PUSH」指令的CPU(如PowerPC或沒有ARM-THUMB代碼的ARM),操作系統必須定義堆棧增長的方向。
更加引人注目的堆棧增長方向的定義是(如果處理器有)中斷堆棧。一些架構(如PowerPC)根本沒有硬件堆棧。然後系統設計人員可以決定實現堆棧的方式:預增,後增。預先遞減或遞減。
在PPC中,調用使用鏈接寄存器,如果返回地址沒有以編程方式保存,則下次調用將覆蓋它。
PPC中斷使用2個特殊寄存器 - 「返回地址」和機器狀態。這是因爲指令可以在中斷之後「重新啓動」 - 一種處理流水線架構中的中斷的方式。
預增量:在存儲在推棧指針指向上次使用的項目之前,堆棧指針遞增。見過更奇怪的8位體系結構(一些第四處理器等)。
後遞增:在堆棧指針遞增之前完成存儲 - 堆棧指針指向第一個空閒堆棧元素。
前後減量:與上面類似,但堆棧向下增長(更常見)。
最常見的是後減量。
可能重複的[是否堆棧向上或向下?](http://stackoverflow.com/questions/1677415/does-stack-grow-upward-or-downward) –
我說的是兩個版本之間的不一致這本書。 – ssj
由於繪製堆棧有兩個約定,因此上下的術語有點令人誤解。但在任何體系結構中找出最簡單的方法是使用-O0編譯一個簡單的函數,並檢查創建堆棧幀的指令是什麼。在我現在使用的系統中,它是'sub r1,#xxx';所以堆棧增長到較小的地址。另一個是從ISA手冊中找到「push x」的解釋。 –