ARM的9種定址方式
1)立即定址
運算元是立即數,以“#”為字首,表示 16 進位制數值時以“0x”表示。
例:
MOV R0,#0xFF00 ;0xFF00 -> R0
SUBS R0,R0,#1 ;R0 – 1 -> R0
2)暫存器定址
運算元的值在暫存器中,指令執行時直接取出暫存器值操作。
例:
MOV R1,R2 ;R2 -> R1
SUB R0,R1,R2 ;R1 - R2 -> R0
3)暫存器偏移定址
當第二運算元是暫存器偏移方式時,第二個暫存器運算元在與第一個運算元結合之前,選擇進行移位操作。
例:
MOV R0,R2,LSL #3 ;R2 的值左移 3 位,結果放入 R0,即 R0 = R2 * 8
ANDS R1,R1,R2,LSL #3 ;R2 的值左移 3 位,然後和 R1 相與操作,結果放入 R1
可採用的移位操作:
LSL:邏輯左移(Logical Shift Left),低端空出位補 0
LSR:邏輯右移(Logical Shift Right),高階空出位補 0
ASR:算術右移(Arithmetic Shift Right),移位過程中符號位不變,即源運算元為正數,則高階空出位補 0,否則補 1
ROR:迴圈右移(Rotate Right),由低端移出位填入高階空出位
RRX:帶擴充套件的迴圈右移(Rotate Right eXtended by 1 place),運算元右移一位,高階空出位用原 C 標誌值填充。
4)暫存器間接定址
運算元儲存在暫存器指定地址的儲存單元中,即暫存器為運算元的地址指標。
例:
LDR R1,[R2] ;將 R2 中的數值作為地址,取出此地址中的資料儲存在 R1 中
SWP R1,R1,[R2] ;將R2中的數值作為地址,取出此地址中的數值與 R1 中的值**
5)基址定址
將基址暫存器的值與偏移量相加,形成運算元的有效地址,基址定址用於訪問基址附近的儲存單元,常用於查表、陣列操作、功能暫存器訪問等。
例:
LDR R2,[R3,#0x0F] ;將R3中的數值加 0x0F 作為地址,取此地址的值儲存在 R2 中
STR R1,[R0,#-2] ;將R0中的數值減 2 作為地址,把 R1的值儲存到此地址中
6)多暫存器定址
一次傳送多個暫存器值,允許一條指令傳送 16 個暫存器的任何子集或所有暫存器。多暫存器定址時,暫存器子集按由小到大的順序排列,連續的暫存器可用“-”連線,否則,用“,”分隔書寫。
例:
LDMIA R1!,{R2-R7,R12} ;將 R1的值讀出到 R2-R7,R12,過程中R1 自動加 1
STMIA R0!,{R3-R6,R10};將 R3-R6,R10的值儲存到 R0 指向的地址,過程中R0 自動加 1
7)堆疊定址
堆疊定址使用堆疊指標SP,即R13,指向堆疊的棧頂。堆疊可分為兩種:
向上生長:向高地址方向生長,稱為遞增堆疊,
向下生長:向低地址方向生長,稱為遞減堆疊,
堆疊指標指向最後壓入的有效資料項,稱為滿堆疊,
堆疊指標指向下一個要放入的空位置,稱為空堆疊,這樣就有 4 種類型的堆疊。
A)滿遞增:堆疊地址向上增長,堆疊指標指向有效資料的最高地址。如 LDMFA,STMFA。
B)空遞增:堆疊地址向上增長,堆疊指標指向堆疊上的第一個空位置。如 LDMEA,STMEA 。
C)滿遞減:堆疊地址向下增長,堆疊指標指向有效資料項的最低地址。如 LDMFD,STMFD。
D)空遞減:堆疊地址向下增長,堆疊指標指向堆疊下的第一個空位置。如 LDMED,STMED 。
例:
STMFD SP!,{R1-R7,LR} ; 將 R1~R7,LR 入棧。滿遞減堆疊。
LDMFD SP!,{R1-R7,LR} ;資料出棧,放入 R1~R7,LR 暫存器。滿遞減堆疊。
8)塊拷貝定址
用於將一塊資料從儲存器的某一位置拷貝到另一位置。
例:
STMIA R0!,{R1-R7} ;將R1~R7的資料儲存到儲存器中,儲存器指標在儲存第一個值之後增加,增長方向為向上增長。
STMIB R0!,{R1-R7} ;將R1~R7的資料儲存到儲存器中,儲存器指標在儲存第一個值之前增加,增長方向為向上增長。
STMDA R0!,{R1-R7} ;將R1~R7的資料儲存到儲存器中,儲存器指標在儲存第一個值之後增加,增長方向為向下增長。
STMDB R0!,{R1-R7} ;將R1~R7的資料儲存到儲存器中,儲存器指標在儲存第一個值之前增加,增長方向為向下增長。
9)相對定址
相對定址是基址定址的一種變通,由程式計數器 PC 提供基準地址,指令中的地址
碼欄位作為偏移量,兩者相加後得到有效地址。
例:
BL ROUTE1 ;呼叫ROUTE1 子程式
BEQ LOOP ;條件跳轉到 LOOP 標號處
…
LOOP MOV R2,#2
…
ROUTE1
…