热门问题
时间线
聊天
视角

堆疊暫存器

来自维基百科,自由的百科全书

Remove ads

堆疊暫存器微處理器中,處理呼叫堆疊暫存器。在以累加器為基礎的處理器中,堆疊暫存器可能是某個特定的暫存器。若是有多個通用暫存器的處理器架構,堆疊暫存器可能是某個依慣例保留的暫存器,像是IBM System/360z/Architecture英語z/Architecture架構以及RISC架構,也有可能是用副程式呼叫或程式返回指令,硬編碼的暫存器,例如PDP-11VAXIntel x86架構。有些處理器(像Data General Eclipse英語Data General Eclipse)沒有專用的堆疊暫存器,而是用保留的硬體記憶體位置來處理此功能。

在1960年末期以前的處理器(例如PDP-8HP 2100英語HP 2100)沒有可以支援遞歸呼叫的編譯器。其程序呼叫指令會將目前程式指標位置儲存在跳躍地址,接著將程式指標設定為下一個位置[1]。此作法比維護堆疊簡單,因為每一個副程式只會有一個返回位址,但除非程式作大幅相關更動,此作法無法支援遞歸呼叫。

堆疊結構機器(Stack machine)可能會有二個或多個堆疊暫存器,其中有一個處理呼叫堆疊,其他暫存器則處理其他堆棧

Remove ads

x86的堆疊暫存器

x86架構16位元的處理器裡,主堆疊暫存器是16位元的堆疊指標(Stack Pointer,SP), 32位元的IA-32裡,擴展為32位元的擴展堆疊指標(Extended Stack Pointer, ESP),64位元的X86-64裡,擴展為64位元的暫存器堆疊指標(Register Stack Pointer,RSP)。堆疊區段暫存器(stack segment register,SS)會儲存目前執行程式呼叫堆疊記憶體分段相關資訊。SP會指向目前堆疊的最頂端。預設情形,堆疊會以記憶體減少的方式成長,因此比較新的資料會放在較低的記憶體位置。PUSH指令可以將值存在堆疊裡,因此堆疊會增加一個資料,POP指令可以提取堆疊中的資訊,並且堆疊會減少一筆資料。

假設SS = 1000h,SP = 0xF820,這表示目前的堆疊頂是在實體地址0x1F820(這是因為Intel 8086的記憶體分區機制),接下來的二個機器碼是

PUSH AX
PUSH BX
  • 第一個指令會將AX(16位元暫存器)的值放在堆疊內,SP數值會減2。
  • 新的SP值是0xF81E。CPU會將AX的值複製到0x1F81E.
  • 執行PUSH BX時,會設定SP為0xF81C,將BX的值複製到0x1F81C[2]

上述就是PUSH運作的原理。一般來說,程式將暫存器的資料PUSH到堆疊是有其目的,例如呼叫會更改暫存器值的副程式。若要提取堆疊中的程式,可以用以下的機器碼

POP BX
POP AX
  • POP BX將0x1F81C位置的字元(是BX原來的值)複製到BX,接著將SP加2,SP值是0xF81E。
  • POP AX將0x1F81E位置的字元複製到AX,接著將SP加2,SP值是0xF820[nb 1][nb 2]
Remove ads

堆疊機

較簡單的處理器會將堆疊指標儲存在一般的硬體暫存器,用算術邏輯單元(ALU)來處理其數值。一般來說push和pop會翻譯為多個微指令,去增加或減少堆疊指標,處理記憶體的讀取和寫入[3]

較新的處理器會有專用的堆疊機(stack engine)以最佳化堆疊操作。Intel的Pentium M是第一個有堆疊機的x86處理器,其實現方式是將堆疊指標分為兩個暫存器:ESPO是32位元的暫存器,ESPd是8位元的偏移值,會依堆疊操作而更新其數值。PUSH、POP、CALL和RET微指令直接對ESPd運作。若If ESPd接近溢位,或是ESP暫存器被其他指令更新(而ESPd ≠ 0),此時會插入同步的微指令,用ALU更新ESPO,並且讓ESPd為0。在後續的Intel處理器中,此機制大致保留,不過將ESPO擴充到64位元[4]

AMD K8微處理器使用一種類似於Intel堆疊機的作法。在其推土機微架構中,不需要加入同步的微指令,但不清楚其堆疊機的內部設計[4]

Remove ads

註解

參考資料

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads