文章目录
所谓的寻址方式,是指当一个指令中的操作数涉及内存访问时,那么指令已什么样的方式来确定内存的地址。
ARM的寻址方式分好几类,这篇笔记记录了数据处理类指令的寻址方式。
数据处理指令
常见的数据处理指令如下表所示,它们支持相同的寻址方式。
助记符 | 说明 | 实现逻辑 |
---|---|---|
MOV | 数据传送 | Rd = Rn(Rn可能需要运算) |
MVN | 数据取反传送 | Rd = ~Rn(Rn可能需要运算) |
ADD | 加 | Rd = Rn + op2 |
ADC | 带进位加 | Rd = Rn + op2 + C |
AND | 逻辑加 | Rd = Rn && op2 |
EOR | 逻辑异或 | Rd = Rn ^ op2 |
SUB | 减 | Rd = Rn - op2 |
SBC | 带进位的减 | Rd = Rn - op2 + C - 1 |
RSB | 反转减 | Rd = op2 - Rn |
RSC | 带进位的反转减 | Rd = op2 - Rn + C - 1 |
TST | 测试 | Rn && op2的结果更新标志位 |
TEQ | 测试相等 | Rn ^ op2的结果更新标志位 |
CMP | 比较 | Rn - op2的结果更新标志位 |
CMN | 符数比较 | Rn + op2的结果更新标志位 |
ORR | 逻辑或 | Rd = Rn || op2 |
BIC | 位清零 | Rd = Rn && ~(op2) |
寻址方式
ARM为数据处理指令支持11种寻址方式。
语法 | 说明 | |
---|---|---|
1 | #<immediate> | 立即数寻址 |
2 | <Rm> | 寄存器寻址 |
3 | <Rm>, LSL #<shift_imm> | 寄存器逻辑左移立即数个位 |
4 | <Rm>, LSL <Rs> | 寄存器逻辑左移寄存器个位 |
5 | <Rm>, LSR #<shift_imm> | 寄存器逻辑右移立即数个位 |
6 | <Rm>, LSR <Rs> | 寄存器逻辑右移寄存器个位 |
7 | <Rm>, ASR #<shift_imm> | 寄存器算数右移立即数个位 |
8 | <Rm>, ASR <Rs> | 寄存器算数右移寄存器个位 |
9 | <Rm>, ROR #<shift_imm> | 寄存器循环右移立即数个位 |
10 | <Rm>, ROR <Rs> | 寄存器循环右移寄存器个位 |
11 | <Rm>, RRX | 寄存器扩展循环右移 |
- 逻辑移位指的是移位后,空余位用0补齐;
- 算数移位指的是移位后,空余位用原Rm[31]的值补齐;
- 循环移位不涉及补齐;
注:尽量避免用R15来用作上述寻址方式,因为流水线技术的原因,R15的值是当前指令的地址加8(3级流水线),这种变化不利于程序编写,此外某些情况下并不能使用R15。
1. 立即数寻址
立即数寻址时,每个立即数由一个8位的常数循环右移偶数位得到,其中循环右移的位数是由一个4bit数字*2表示。所以,并不是每一个32位的立即数都能通过这种方式指定,只有通过这种方式能够构造得到的立即数才是合法的。
立即数寻址的伪代码如下:
语法:#<immediate>
shifter_operand = immed_8 Rotate_Right (rotate_imm * 2)
if rotate_imm == 0 then
shifter_carry_out = C flag
else
shifter_carry_out = shifter_operand[31]
心得:首先,个人理解没有必要去研究到底一个立即数是否合法,编码时可以直接让汇编器帮忙检查;并且如果无法表示该立即数,我们可以通过ldr伪指令来将任意一个立即数传送到寄存器中,然后使用寄存器寻址方式来代替立即数寻址。
2. 寄存器寻址
语法: <Rm>
shifter_operand = Rm
shifter_carry_out = C flag
3. 寄存器逻辑左移立即数寻址
语法:<Rm>, LSL #<shift_imm>
if shift_imm == 0 then
shifter_operand = Rm
shifter_carray_out = C flag
else
shifter_operand = Rm Logical_Shift_Left shift_imm
shifter_carry_out = Rm[32 - shift_imm]
4. 寄存器逻辑左移寄存器寻址
语法:Rm>, LSL <Rs>
if Rs[7:0] == 0 then
shifter_operand = Rm
shifter_carray_out = C flag
elif Rs[7:0] < 32 then
shifter_operand = Rm Logical_Shift_Left Rs[7:0]
shifter_carry_out = Rm[32 - Rs[7:0]]
elif Rs[7:0] == 32 then
shifter_operand = 0
shifter_carry_out = Rm[0]
else
shifter_operand = 0
shifter_carry_out = 0
5. 寄存器逻辑右移立即数寻址
语法:<Rm>, LSR #<shift_imm>
if shift_imm == 0 then
shifter_operand = 0
shifter_carray_out = Rm[31]
else
shifter_operand = Rm Logical_Shift_Right shift_imm
shifter_carry_out = Rm[shift_imm - 1]
6. 寄存器逻辑右移寄存器寻址
语法:<Rm>, LSR <Rs>
if Rs[7:0] == 0 then
shifter_operand = Rm
shifter_carray_out = C flag
elif Rs[7:0] < 32 then
shifter_operand = Rm Logical_Shift_Right Rs[7:0]
shifter_carry_out = Rm[Rs[7:0] - 1]
elif Rs[7:0] == 32 then
shifter_operand = 0
shifter_carry_out = Rm[31]
else
shifter_operand = 0
shifter_carry_out = 0
7. 寄存器算数右移立即数寻址
语法:Rm>, ASR #<shift_imm>
if shift_imm == 0 then
shifter_carray_out = Rm[31]
if Rm[31] == 0 then
shifter_operand = 0
else
shifter_operand = 0xFFFF_FFFF
else
shifter_operand = Rm Arithmetic_Shift_Right shift_imm
shifter_carry_out = Rm[shift_imm - 1]
8. 寄存器算数右移寄存器寻址
语法:<Rm>, ASR <Rs>
if Rs[7:0] == 0 then
shifter_operand = Rm
shifter_carray_out = C flag
elif Rs[7:0] < 32 then
shifter_operand = Rm Arithmetic_Shift_Right Rs[7:0]
shifter_carry_out = Rm[Rs[7:0] - 1]
elif Rs[7:0] == 32 then
shifter_operand = 0
shifter_carry_out = Rm[31]
else
shifter_carry_out = Rm[31]
if Rm[31] == 0 then
shifter_operand = 0
else
shifter_operand = 0xFFFF_FFFF
9. 寄存器循环右移立即数寻址
语法:<Rm>, ROR #<shift_imm>
if shift_imm == 0 then
见“”介绍
else
shifter_operand = Rm Rotate_Right shift_imm
shifter_carry_out = Rm[shift_imm - 1]
10. 寄存器循环右移寄存器寻址
语法:<Rm>, ROR <Rs>
if Rs[7:0] == 0 then
shifter_operand = Rm
shifter_carray_out = C flag
elif Rs[4:0] < 32 then
shifter_operand = Rm
shifter_carray_out = Rm[31]
else
shifter_operand = Rm Rotate_Right Rs[4:0]
shifter_carry_out = Rm[Rs[4:0]- 1]
11. 寄存器扩展循环右移寻址
语法:<Rm>, RRX
shifter_operand = (C Flag Logical_Shift_Left 31) || (Rm Logical_Shift_Right 1)
shifter_carry_out = Rm[0]