Arm入门第八讲,ARM中的寻址方式
Arm入门第八讲,ARM中的寻址方式。
一丶寻址方式
1.1 什么是寻址
寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式。ARM指令系统支持如下几种常见的寻址方式。
1.2 寻址方式
立即寻址
立即寻址,也称为立即数寻址,这是一种特殊的寻址方式,操作数本身就在指令中给出,只要取出指令也就取到了操作数,这个操作数被称为立即数,对应的寻址方式也就称为立即寻址。
指令如下:
ADD RO,R0,#1 ; R0 = R0 + 1
ADD R0,R0,#0X3f ; R0 = R0 + 0X3f
在上面的两条指令中,第二个源操作数即为立即数,要求以“#”为前缀,对于以十六进制表示的立即数,还要求在“#”后加上“0x或者&”
寄存器寻址
寄存器寻址就是利用寄存器中的数值为操作数,这种方式是各种微处理器经常采用的一种方式,也是效率较高的寻址方式。
ADD R0,R1,R2; R0 = R1 + R2
该指令的执行效果是将寄存器R1和R2的内容相加,其结果存放在寄存器R0中。
寄存器间接寻址
寄存器间接寻址就是以寄存器中的值为操作数的地址,而操作数本身则存放在存储器中。
ADD R0,R1,[R2]; R0 =R1 + [R2]
LDR R0,[R1]; R0 = [R1]
STR R0,[R1] [R1] = R0
在第一条指令中,以寄存器R2的值作为操作数的地址,在存储器中取得一个操作数后与R1相加,结果存入寄存器R0中。第二条指令将以R1的值为地址的存储器中的数据传送到R0中。第三条指令将R0的值传送到以R1的值为地址的存储器中。
基址变址寻址
基址变址寻址就是寄存器的内容与指令给出的地址偏移量的相加,从而得到一个操作数的有效地址。 变址寻址方式常用语访问某基地址附近的地址单元。指令如下:
LDR R0,[R1,#4]; R0 = [R1+4]
LDR R0,[R1,#4]!; R0 = R1 + 4; R1 = R1 + 4;
LDR R0,[R1],#4; R0 = [R1] R1 = R1 + 4;
LDR R0,[R1,R2]; R0 =[R1 + R2]
在第一条指令中,将寄存器R1的内容加上4形成操作数的有效地址,从而取得操作数存入寄存器R0中。在第二条指令中,将寄存器R1的内容加上4形成操作数的有效地址,从而取得操作数存入寄存器R0中,然后,R1的内容自增4个字节。在第三条指令中,以寄存器R1的内容作为操作数的有效地址,从而取得操作数存入寄存器R0中,然后,R1的内容自增4个字节。在第四条指令中,将寄存器R1的内容加上寄存器R2的内容形成操作数的有效地址,从而取得操作数存入寄存器R0中。
多寄存器寻址
采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。 这种寻址方式可以用一条指令完成传送最多16个通用寄存器的值。
LDMIA R0,{R1,R2,R3,R4}
R1 = [R0 + 0x0]
R2 = [R0 + 0x4]
R3 = [R0 + 0x8]
R4 = [R0 + 0xC]
后缀指令为IA,意思是在每次执行完加载、存储操作后,R0按照字节长度增加,因此指令可以将连续存储单元的值传送给R1-R4
相对寻址
与基址变址寻址方式相类似,相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。
BL NEXT 跳转到子程序NEXT处执行
......
NEXT
......
MOV PC,LR; 从子程序返回
堆栈寻址
堆栈是一种数据结构,先进后出的方式工作,使用一个称为堆栈指针的专用寄存器保存当前的操作位置,堆栈指针总是指向栈顶。
ARM指令中有 LDM 批量加载 STM批量存储指令。
lDM(或者STM) {条件}{类型} 基址寄存器{!},寄存器列表{^}
LDM是从基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据。 STM则是相反。
按照堆栈方式又分为 FA(满递增栈) FD(满递减栈 常用) EA (空递增栈) ED(空递减栈) 这些在前面已经说过了。
{!}为可选后缀,若是使用这个后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。
基址寄存器不允许位R15(PC)寄存器列表可以是R0~R15的任意组合。
{^}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用这个后缀则表示: 除了正常的数据传送之外,还将SPSR复制到CPSR。 同时该后缀还表示传入或传出的的是用户模式下的寄存器,而不是当前模式下的寄存器。
STMFD R13!,{R0,R1,R2,R14};
STMFD R13!,{R0,R4-R12,LR}; 将寄存器R0,R4到R12和LR(R14)存入堆栈。
LDMFD R13!,{R0,R4-R12,PC}; 将堆栈内容恢复到寄存器R0,R4-R12,PC中。
小提示:
① 一个范围的寄存器表示可以简单地只写第一个和最后一个,并在其间加一个横杠。例如R0-R3等同与R0, R1, R2, R3。
② 大括号中的数据表示要进行操作的寄存器列表,寄存器与寄存器之间以逗号间隔。‘!’为回写符,更新R13中的值。