ARM的棧指令


ARM的指令系統中關於棧指令的內容比較容易引起迷惑,這是因為准確描述一個棧的特點需要兩個參數:

  • 棧地址的增長方向:ARM將向高地址增長的棧稱為遞增棧(Descendent Stack),將向低地址增長的棧稱為遞減棧(Acendant Stack)
  • 棧指針的指向位置:ARM將棧指針指向棧頂元素位置的棧稱為滿棧(Full Stack),講棧指針指向即將入棧的元素位置的棧稱為空棧(Empty Stack)

1. 棧類型

根據棧地址增長方向雨棧指針指向位置的不同,自然可以將棧分為四類:

遞增棧 遞減棧
空棧 EA棧 ED棧
滿棧 FA棧 FD棧

圖1描述了四種不同類型的棧,其中虛線部分表示即將入棧的元素。


圖1 棧類型

2. 棧指令

棧的操作指令無非兩種:入棧和出棧,由於ARM描述了四種不同類型的棧,因此對應的棧指令一共有8條。

入棧 出棧
EA棧 STMEA LDMEA
ED棧 STMED LDMED
FA棧 STMFA LDMFA
FD棧 STMFD LDMFD

這些指令具有相似的前綴:

  • STM:(STore Multiple data)表示存儲數據,即入棧
  • LDM:(LoaD Multiple data)表示加載數據,即出棧

一般情況下,可以將棧操作指令分解為兩步微指令:數據存取和棧指針移動。這兩步操作的先后順序和棧指針的移動方式由棧的類型決定。

第一步 第二步 等價指令
STMEA 寫[SP] SP增加 STMIA
LDMEA SP減少 讀[SP] LDMDB
STMED 寫[SP] SP減少 STMDA
LDMED SP增加 讀[SP] LDMIB
STMFA SP增加 寫[SP] STMIB
LDMFA 讀[SP] SP減少 LDMDA
STMFD SP減少 寫[SP] STMDB
LDMFD 讀[SP] SP增加 LDMIA

ARM中存在一組緩沖區操作指令和棧指令是一一對應的,他們完成相同的功能。這些指令含義的區別來源於對存取操作的緩沖區指針地址增長方向,以及存取操作和緩沖區指針移動的先后順序決定的。這個和前面描述的棧類型的分類原則十分相似。

指針遞增(Increase) 指針遞減(Decrease)
存取前移動指針(Before) IB DB
存取后移動指針(After) IA DA

3. 使用舉例

雖然ARM的棧類型和相關的操作指令比較繁瑣,但是實際上最常用的還是和x86指令集相同的棧類型:棧向低地址方向增長,且棧指針指向棧頂元素的位置,即ARM的FD棧。因此最常見的ARM棧指令操作是STMFD和LDMFD。

x86 ARM
入棧 PUSH STMFD/STMDB
出棧 POP LDMFD/LDMIA

例如入棧指令:

STMFD SP,{R0-R3}

實際的微指令操作為:

[SP-4]	<=	R3
[SP-8]	<=	R2
[SP-12]	<=	R1
[SP-16]	<=	R0

在ARM的指令系統中,遞減棧入棧操作的參數入棧順序是從右到左依次入棧,而參數的出棧順序則是從左到右的逆操作。對於遞增棧,相應的操作則全部取反。
例如出棧指令:

LDMFD SP,{R4-R7}

實際的微指令操作為:

[SP]    =>	R4
[SP+4]	=>	R5
[SP+8]	=>	R6
[SP+12]	=>	R7

上述的入棧和出棧指令其實僅僅對棧做了存取操作,並未真正改變SP指針的值。正常情況下,我們希望對棧操作后能自動修改棧指針SP的值,使用如下指令可以達到該目的。

STMFD SP!,{R0-R3}

對應的微指令操作為:

[SP-4]	<=	R3
[SP-8]	<=	R2
[SP-12]	<=	R1
[SP-16]	<=	R0
SP      =  SP - 16

同樣的:

LDMFD SP!,{R4-R7}

對應的微指令操作為:

[SP]    =>	R4
[SP+4]	=>	R5
[SP+8]	=>	R6
[SP+12]	=>	R7
SP      =  SP + 16

希望通過本文對你理解ARM的棧指令有所幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM