这篇笔记记录的是操作32位子类型和无符号字节数据的Load/Store指令所使用的寻址方式。
所有类型的Load/Store指令的寻址方式都是由基址加偏移量组成的,基址用任意的通用寄存器指定,偏移量的指定方式有如下三种:
- 立即数;
- 寄存器;
- 寄存器和一个移位常数;
寻址方式的计算又有如下三种方式:
- 偏移量方法;
- 事先更新方法:先计算访存地址,然后访存,最后用访存地址更新基址寄存器,也叫事后访问方式(事后指的是访存操作后于更新地址);
- 事后更新方法:先用基址寄存器值访存,然后计算新的访存地址,最后用新的访存地址更新基址寄存器,也叫事先访问方式(事先指的是访存操作先于更新地址);
注意:上述内容适用于所有类型的Load/Store指令。
语法格式
操作32位子类型和无符号字节数据的Load/Store指令的语法格式如下:
LDR{<cond>}{B} {T}<Rd>, <address_mode>
- B表示操作的是无符号字节;
- T表示以用户模式权限执行指令,具体见指令介绍。
寻址方式
操作32位子类型和无符号字节数据的Load/Store指令共有9种寻址方式,下面一一介绍。
语法 | 说明 | |
---|---|---|
1 | [<Rn>, #+/-<offset_12>] | 立即数偏移量寻址 |
2 | [<Rn>, +/-<Rm>] | 寄存器偏移量寻址 |
3 | [<Rn>, +/-<Rm>, <shift>#<shift_imm>] | 寄存器移位偏移量寻址 |
4 | [<Rn>, #+/-<offset_12>]! | 立即数事先更新寻址 |
5 | [<Rn>, #+/-<Rm>]! | 寄存器事先更新寻址 |
6 | [<Rn>, +/-<Rm>, <shift>#<shift_imm>]! | 寄存器移位事先更新寻址 |
7 | [<Rn>], #+/-<offset_12> | 立即数事后更新寻址 |
8 | [<Rn>], +/- | 寄存器事后更新寻址 |
9 | [<Rm>], +/-<Rn>, <shift>#<shift_imm> | 寄存器移位事后更新寻址 |
立即数偏移量寻址
[<Rn>, #+/-<offset_12>]
if U == 1 then
address = Rn + offset_12
else
address = Rn - offset_12
寄存器偏移量寻址
[<Rn>, +/-<Rm>]
if U == 1 then
address = Rn + Rm
else
address = Rn - Rm
寄存器移位偏移量寻址
[<Rn>, +/-<Rm>, <shift>#<shift_imm>]
根据<shift>的不同,总共有如下几种移位偏移量寻址方式:
逻辑左移:[<Rn>, +/-<Rm>, LSL #<shift_imm>]
逻辑右移:[<Rn>, +/-<Rm>, LSR #<shift_imm>]
算数右移:[<Rn>, +/-<Rm>, ASR #<shift_imm>]
循环右移:[<Rn>, +/-<Rm>, ROR #<shift_imm>]
扩展循环右移:[<Rn>, +/-<Rm>, RRX]
case LSL:
index = Rm LSL shift_imm
case LSR:
if shift_imm == 0 then // 右移32位
index = 0
else
index = Rm LSR shift_imm
case ASR:
if shift_imm == 0 then // 右移32位
if Rm[31] == 1 then
index = 0xFFF_FFFF
else
index = 0
else
index = Rm ASR shift_imm
case ROR | RRX
if shift_imm == 0 then // RRX
index = (C Flag LSL 31) OR (Rm LSR 1)
else // ROR
index = Rm ROR shift_imm
if U == 1 then
address = Rn + index
else
address = Rn - index
立即数事先更新寻址
[<Rn>, #+/-<offset_12>]!
if U == 1 then
address = Rn + offset_12
else
address = Rn - offset_12
if CondPassed then
Rn = address
寄存器事先更新寻址
[<Rn>, #+/-<Rm>]!
if U == 1 then
address = Rn + Rm
else
address = Rn - Rm
if CondPassed then
Rn = address
寄存器移位事先更新寻址
[<Rn>, +/-<Rm>, <shift>#<shift_imm>]!
类似的,根据<shift>的不同,总共有如下几种移位偏移量寻址方式:
逻辑左移:[<Rn>, +/-<Rm>, LSL #<shift_imm>]!
逻辑右移:[<Rn>, +/-<Rm>, LSR #<shift_imm>]!
算数右移:[<Rn>, +/-<Rm>, ASR #<shift_imm>]!
循环右移:[<Rn>, +/-<Rm>, ROR #<shift_imm>]!
扩展循环右移:[<Rn>, +/-<Rm>, RRX]!
case LSL:
index = Rm LSL shift_imm
case LSR:
if shift_imm == 0 then // 右移32位
index = 0
else
index = Rm LSR shift_imm
case ASR:
if shift_imm == 0 then // 右移32位
if Rm[31] == 1 then
index = 0xFFF_FFFF
else
index = 0
else
index = Rm ASR shift_imm
case ROR | RRX
if shift_imm == 0 then // RRX
index = (C Flag LSL 31) OR (Rm LSR 1)
else // ROR
index = Rm ROR shift_imm
if U == 1 then
address = Rn + index
else
address = Rn - index
if CondPassed then
Rn = address
立即数事后更新寻址
[<Rn>], #+/-<offset_12>
address = Rn
if CondPassed then
if U == 1 then
Rn = Rn + offset_12
else
Rn = Rn - offset_12
寄存器事后更新寻址
[<Rn>], +/-<Rm>
address = Rn
if CondPassed then
if U == 1 then
Rn = Rn + Rm
else
Rn = Rn - Rm
寄存器移位事后更新寻址
[<Rm>], +/-<Rn>, <shift>#<shift_imm>
类似的,根据<shift>的不同,总共有如下几种移位偏移量寻址方式:
逻辑左移:[<Rn>], +/-<Rm>, LSL #<shift_imm>
逻辑右移:[<Rn>], +/-<Rm>, LSR #<shift_imm>
算数右移:[<Rn>], +/-<Rm>, ASR #<shift_imm>
循环右移:[<Rn>], +/-<Rm>, ROR #<shift_imm>
扩展循环右移:[<Rn>], +/-<Rm>, RRX
address = Rn
case LSL:
index = Rm LSL shift_imm
case LSR:
if shift_imm == 0 then // 右移32位
index = 0
else
index = Rm LSR shift_imm
case ASR:
if shift_imm == 0 then // 右移32位
if Rm[31] == 1 then
index = 0xFFF_FFFF
else
index = 0
else
index = Rm ASR shift_imm
case ROR | RRX
if shift_imm == 0 then // RRX
index = (C Flag LSL 31) OR (Rm LSR 1)
else // ROR
index = Rm ROR shift_imm
if CondPassed then
if U == 1 then
Rn = Rn + index
else
Rn = Rn - index