学习过C语言编译的四个阶段的都知道,C文件通过预处理和编译形成汇编文件,汇编文件就是由一条条汇编指令组成。汇编指令可以通过ARM汇编手册翻译成二进制。
ARM寻址方式是指根据指令中操作数的信息来寻找操作数实际物理地址的方式。根据指令中操作数的不同格式,ARM支持的寻址方式有立即数寻址,寄存器寻址,寄存器间接寻址,基址变址寻址,多寄存器寻址,相对寻址和堆栈寻址。
1. 指令的表示方式
32位的ARM的机器,指令的表示格式是由32位的二进制表示,CPU根据二进制的代码完成所需要的操作,如下是一条指令的示意图
ARM指令分为五个域,第一个是条件码域,如图cond,第二个是指令代码域,如图opcode,第三个是地址基址域,如图Rn,第四个是目标或源寄存器,如图Rd,第五个是地址偏移或操作寄存器,如图op2。
2. 指令格式
< > :表示其中内容不可缺少;{ } :表示内容可省略
{
{S} :决定指令执行是否会影响CPSR的值,使用该后缀则指令执行会影响CPSR的值,否则不影响。
示例:
LDR R0, [R1] ; 读取R1地址上的存储单元的数据到寄存器R0
BEQ ENDDATA ; 如果上一条指令执行条件相等,则跳转到ENDDATA
ADDS R2, R1, #1 ; 寄存器R1的内容加1后存入寄存器R2,并影响CPSR寄存器。
1. 立即数寻址
当操作数是立即数的指令,对应的寻址方式成为立即数寻址
举例:
MOV R0, #15 ; #15为立即数,立即数以"#"为前缀,十六进制的立即数以0x表示,二进制的立即数以0b表示。
2. 寄存器寻址
利用寄存器中的数值作为操作数。
举例:
ADD R0, R1, R2 ; R0 <= R1 + R2
3. 寄存器间接寻址
以寄存器中的值作为操作数的地址,操作数本身存放在存储器中。
举例:
LDR R0, [R4] ; R0 <= [R4]
4. 寄存器以为寻址
寄存器移寻址的操作数由寄存器中的数值做相应移位而得到。
举例:
ADD R0, R1, R2, LSL #1
MOV R0, R1, LSL R3
5. 基址变址寻址
将寄存器的内容与指令中给出的地址偏移量相加,从而得到一个操作数的有效地址。
举例:
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]
6. 多寄存器寻址
采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。一次最多可以传送16个通用寄存器的值,连续的寄存器之间用"-",否则用","分隔。
举例:
LDMIA R0!, {R0-R4} ; R1 <= [R0]
; R2 <= [R0+4]
; R3 <= [R0+8]
; R4 <= [R0+12]
7. 相对寻址
相对寻址以程序计数器PC的当前值为基地址,指令的地址标号作为偏移量,将两者相加得到操作数的有效地址。
举例:
BL proc
proc:
MOV R0, #1
跳转到proc处运行
32位CPU的ARM指令可以被翻译成4字节的机器码,可以被机器识别。ARM寻址方式有立即数寻址,寄存器寻址,寄存器间接寻址,寄存器移位寻址,基址变址寻址,多寄存器寻址,相对寻址。