ARM寻址方式
ARM处理器拥有以下九种基本寻址方式:
①立即数寻址
②寄存器寻址
③寄存器间接寻址
④寄存器偏移寻址
⑤基址变址寻址
⑥多寄存器寻址
⑦堆栈寻址
⑧块拷贝寻址
⑨相对寻址
以下逐一对各种寻址方式进行介绍:
1、立即数寻址
数据包含在指令中,取出指令时也就取出了可以立即拿来使用的操作数(立即数)
示例:
-
SUBS R0,R0,#1 @1是立即数,R0-1,结果放入R0,并影响标志位
判断是否为合法立即数的方法:
必须为8位位图,即是由一个8位的常数循环移位偶数位来得到的。
判断方法:1、该数的二进制表示方法中1的个数是否不超过8个
2、8个以下的1能否放在连续的八个位里
3、能不能循环移位偶数位来得到要的那个数
(其实三个点就是为了满足8位位图的要求)
用ldr伪指令可以解决不合法有理数:
用mov进行立即数给寄存器赋值,必须是合法立即数。但如果是用“ LDR 寄存器 ,=立即数”
就没有对立即数范围的限制。它内部是这样实现的:如果这个立即数是合法的,也就是满足mov的要求,它就跟mov一样,只用一条汇编指令帮你实现了,当不是合法立即数时,它会用其他方法帮你实现。
比如:ldr r1, =0x12345678
如果这个立即数是合法的(符合mov要求),它就用mov指令来代替;
如果这个立即数不是合法的,真正的汇编代码是将一个地址的值传给r1,这个地址存放着这个立即数。
【ldr和ldr伪指令不是同一个东西】
ldr是这样的:ldr r0,0x12345678 是把这个地址里放的数据存放到r0里来,是用来在cpu和内存间传递数据的。不要和ldr伪指令混淆。
2、寄存器寻址
操作数在寄存器中,指令中取出寄存器编号,取出寄存器的值来操作
示例:
-
MOV R1,R2
@将R2的值存入R1
3、寄存器间接寻址
寄存器中保存着操作数的地址,指令中取出寄存器编号,拿出操作数的地址。
示例:
-
LDR R1,[R2]
@将R2指向的存储单元的数据读出来保存到R1中
4、寄存器偏移寻址
第二个操作数是寄存器移位方式时,第二个寄存器先进行移位。
示例:
-
MOV R0,R2,LSL #3
@R2的值左移三位,放入R0,即R0=R2x8
5、基址变址寻址
将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址。
示例:
-
LDR R2,[R3,#0X0C]
@读取R3+0X0C地址上的内容,放入R2
6、多寄存器寻址
一次可传送几个寄存器的值。
示例:
-
LDMIA R1!,{R2-R4,R6}
@将R1指向的单元中的数据读出到R2-R4,R6中,R1自动更新
7、堆栈寻址
“后进先出” 使用专门的寄存器(堆栈指针SP)指向一块存储区域
①递增堆栈:低地址→高地址
②递减堆栈:高地址→低地址(ARM是使用递减堆栈)
①满堆栈:堆栈指针指向最后压入的有效数据项(ARM是满堆栈)
②空堆栈:堆栈指针指向下一个待压入数据的空位置
8、块拷贝寻址
将一块数据从存储器的某一位置拷贝到另一位置。
示例:
STMIA R1!,{R3-R9} @将R3~R9的数据存储到R1指向的地址上,R1值更新
9、相对寻址
类似基址寻址,用程序计数器PC提供基准地址。 地址码字段为偏移量,两者相加后为操作数的有效地址。