ARM寻址方式
寻址方式
寻址方式是根据指令中给出的地址码字段来实现寻找操作数地址的方式,ARM中有以下8种基本的寻址方式。
1、寄存器寻址
将寄存器中的值作为操作数,指令中的地址码字段是寄存器编号。
MOV R1,R2 ;R1 = R2
ADD R0,R1,R2 ;R0 = R1 + R2
2、立即寻址
将操作数直接写到指令中,取出指令也就取出操作数,直接使用。
MOV R1,#0xFFF0 ;R1 = 0xFFF0
SUBS R1,R1,#0xF0 ;R1 = R1 - 0xF0
3、寄存器移位寻址
寄存器移位寻址是ARM指令集特有的寻址方式。当第2个操作数是寄存器移位方式时,第2个寄存器操作数在与第1个操作数结合之前,选择进行移位操作。
MOV R0,R1,LSR #2 ;R1的值右移2位,结果放入R0
ANDS R1,R1,R2,LSL R3 ;R2的值左移R3位,然后和R1“与”操作,结果放入R1
其中移位操作有
LSR(Logical Shift Right)逻辑右移,高位补0
LSL(Logical Shift Left)逻辑左移,低位补0
ASR(Arithmetic Shift Right)算术右移,符号位不变,高位补符号位数值
ROR(ROtate Right)循环右移,低位补高位
RRX(ROtate Right eXtended by 1 place),操作数右移1位,高位补C标志位
4、寄存器间接寻址
操作数是以寄存器中的值作为地址所对应的值,即寄存器中的值为操作数的地址指针。
LDR R1,[R2] ;R1 = *R2
SWP R1,R1,[R2] ;交换R1和*R2
5、基址寻址
将基址寄存器的内容加上需要的偏移量,得到需要操作数的有效地址,常用于查表和数组操作。
LDR R1,[R2,#0xFC] ;R1 = *(R2+0xFC)
LDR R1,[R2,#0xFC]! ;R1 = *(R2+0xFC),R2 = R2 + 0xFC
STR R1,[R2,#0xFC]! ;R2 = R2 + 0xFC,*R2 = R1
LDR R0, [R1, R2] ;R0 = *(R1+R2)
6、多寄存器寻址
一条指令可以完成多个寄存器值得传送,一条指令可以传送16个寄存器的任何自己和所有寄存器。
LDMIA R1!,{R2-R7,R12} ;将R1指向的单元中的数据读到R2-R7,R12中,R1++
STMIA R0!,{R2-R7,R12} ;中将R2-R7,R12中的值保存到R1指向的单元,R0++
7、堆栈寻址
堆栈指针移动方向称生长方向,ARM7有:
- 向上生长,向堆栈写入数据后,堆栈指针(SP)值变大,往高地址生长
- 向下生长,向堆栈写入数据后,堆栈指针(SP)值变小,往低地址生长
除SP移动方向有所不同,SP指向的位置也有所不同:
- SP指向最后压入栈的有效数据项,称满堆栈,入栈时应该先调整指针后写入数据
- SP指向下一个待压入数据的空位置,称空堆栈,入栈时应该先写入数据后调整指针
根据SP生长方向和指向位置不同组合,得到4中堆栈类型:
- 满递增,LDMFA,STMFA
- 空递增,LDMEA,STMEA
- 满递减,LDMFD,STMFD
- 空递减,LDMED,LDMED
STMFD SP!,{R!-R7,LR} ;R1-R7,LR入栈,满递减
LDMFD SP!,{R!-R7,LR} ;数据出栈,放入R1-R7,LR寄存器,满递减
8、相对寻址
与基址寻址类似,以程序计数器PC为基准地址,指令中声明偏移量,相加即得到操作数的有效地址。
BL SUBR1 ;调用子程序SUBR1
BEQ LOOP ;条件跳转到LOOP标号处
.....
LOOP MOV R6,#1
......
SUBR1 ......