在 ARM 架構中,STMFD(Store Multiple Full Descending)與 LDMFD(Load Multiple Full Descending)是兩條核心的堆疊操作指令,廣泛用於現場保護、數據複製、參數傳遞等場景。它們屬於「全遞減」堆疊模型,即堆疊指針(SP)指向已使用的最後一個地址,壓棧時 SP 先減後存,彈棧時先取後增。
STMFD Rn{!}, {reglist}{^}
SP = SP - 9*4; // 9 個寄存器,每個 4 字節
address = SP;
for i = 0 to 7:
Memory[address] = Ri;
address = address + 4;
Memory[address] = LR;
假設初始 SP = 0x40000460,執行 STMFD SP!, {R0-R7, LR} 後,堆疊佈局如下圖所示(藍色區塊為記憶體地址):
STMFD 指令操作示意
壓棧後的堆疊分佈
LDMFD Rn{!}, {reglist}{^}
含義:以 Rn 為基址(起始地址),依序將記憶體數據讀入寄存器列表。
address = SP;
for i = 0 to 7:
Ri = Memory[address, 4];
address = address + 4;
SP = address;
假設執行前 SP = 0x4000043C,執行 LDMFD SP!, {R0-R7, PC}^ 後,堆疊變化如下(藍色為執行前 SP,紅色為執行後 SP):
LDMFD 指令操作示意
彈棧後的堆疊分佈
| 特性 | STMFD (壓棧) | LDMFD (彈棧) |
|---|---|---|
| 堆疊方向 | 全遞減(向低地址增長) | 全遞減(向高地址縮減) |
| SP 變化 | 先減後存 | 先取後增 |
| 典型用途 | 函數入口保存現場、中斷入口 | 函數返回恢復現場、中斷返回 |
| 寄存器順序 | 按編號遞增存入(R0 先存,位於低地址) | 按編號遞增讀出(R0 先讀,來自低地址) |
STMFD SP!, {...} 與 LDMFD SP!, {...} 必須嚴格對應相同的寄存器列表,否則會導致堆疊失衡。PC 作為目標寄存器時(如 LDMFD SP!, {..., PC}^),會直接引發分支跳轉,常用於中斷返回或函數尾調用。^ 後綴在特權模式下會觸發用戶模式寄存器存取,需謹慎使用。