ARM汇编语法格式
<
o
p
c
o
d
e
>
{
c
o
n
d
}
{
S
}
<
R
d
>
,
<
R
n
>
,
<
s
h
i
f
t
e
r
_
o
p
e
r
a
n
d
>
<opcode>\{cond\}\{S\}<Rd>,<Rn>,<shifter\_operand>
<opcode>{cond}{S}<Rd>,<Rn>,<shifter_operand>
- opcode:指令助记符,如ADD、SUB、MOV等;
- cond:条件码助记符,如EQ(0000)、NE(0001)、AL(1110)等;
- S:如果指令有S后缀,则该指令的操作会影响CPSR的值;
- Rd:目标寄存器;
- Rn:包含第一个源操作数的寄存器;
- shifter_operand:表示第二个源操作数,可以为寄存器或立即数。
所谓寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式。
立即寻址
< o p c o d e > { c o n d } { S } < R d > , < R n > , # < i m m e d i a t e > <opcode>\{cond\}\{S\}<Rd>, <Rn>, \#<immediate> <opcode>{cond}{S}<Rd>,<Rn>,#<immediate>
- 立即寻址也叫立即数寻址,这是一种特殊的寻址方式,
操作数本身就在指令中给出,只要取出指令也就取到了操作数。
ADD R0,R0,#1 ;R0←R0+1
ADD R0,R0,#0x3f ;R0←R0+0x3f
- 在以上两条指令中,第二个源操作数即为立即数,
要求以“#”为前缀
,对于以十六进制表示的立即数,还要求在“#”后加上“0x”或“&” ,另外%表示二进制数。
合法的立即数
- 所有的ARM指令都是32 bits固定长度,没有任何一条ARM 指令可包括一个32 bit的立即数。
- immediate:立即数
- immed_8:8 位的常数
- rotate_imm:4 位的循环右移值
- 每个立即数都是
由一个 8 位的常循环右移偶数位得到
- 4 bit 移位值 (0-15)乘于2,得到一个范围在0-30,步长为2的移位值。
最后8位一定要移动偶数位
- 合法的立即数:
二进制有效位间隔不超过8位,且后面的0为偶数个
< i m m e d i a t e > = i m m e d _ 8 循 环 右 移 ( 2 ∗ r o t a t e _ i m m ) <immediate>=immed\_8 循环右移(2∗rotate\_imm) <immediate>=immed_8循环右移(2∗rotate_imm)
- ROR 循环右移:即将操作数循环按指定的数量向右循环移位,左边用右边移出的位来填充
- 下列命令中,汇编器把立即数转换为移位操作
MOV r0,#4096 ;uses 0x40 ROR 26
ADD r1,r2,#0xFF0000 ;; uses 0xFF ROR 16
;也可使用 MVN来进行位反转:
MOV r0, #0xFFFFFFFF ;; assembles to MVN r0,#0
寄存器寻址
- 寄存器寻址就是
利用寄存器中的数值作为操作数
,这种寻址方式是各类微处理器经常采用的一种方式,也是一种执行效率较高的寻址方式
ADD R0,R1,R2 ;R0←R1+R2
寄存器间接寻址
- 寄存器间接寻址就是
以寄存器中的值作为操作数的地址
,而操作数本身存放在存储器中。
LDR R0,[R1] ;R0←[R1]
STR R0,[R1] ;[R1]←R0
基址变址寻址
- 基址变址寻址就是将
寄存器(该寄存器一般称作基址寄存器)的内容与指令中给出的地址偏移量相加
,从而得到一个操作数的有效地址。 - 变址寻址方式常用于访问某基地址附近的地址单元。
- 地址偏移量通常有以下三种表示方式
- 常量
- 寄存器
- 比例
偏移寻址(offset addressing)
- 使用一个绝对值不大于4095的数值,可使用带符号数,即在-4095~+4095之间; 如:
LDR R2, [Rn, #-0x8]
- 使用寄存器偏移的方法计算偏移量;如:
LDR R2, [Rn, -R3]
- 使用对寄存器移位的方法计算偏移量;如:
LDR R2, [Rn, R3,LSL #2]
- 使用语句标号。如:
LDR R2, START ;R2<-[START]
- 在这种寻址方式中,
程序计算器PC是隐含的基址寄存器
,偏移量是语句标号所在的地址和PC(当前正在执行的指令)之间的差值。
- 在这种寻址方式中,
事先/事后 更新寻址
- Pre-indexed:
STR r0,[r1,#12]!
- Post-indexed:
STR r0,[r1],#12
多寄存器寻址
- 采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。
这种寻址方式可以用一条指令完成传送最多16个通用寄存器的值。
LDMIA R13,{R1,R2,R3,R4}
;或写成:LDMIA R13,{R1-R4}
;R1←[R13]
;R2←[R13+4]
;R3←[R13+8]
;R4←[R13+12]
- 该指令的后缀IA表示在每次执行完加载/存储操作后,
Rn按字长度增加
,因此,指令可将连续存储单元的值传送到R1~R4。- IA (increment after) 事后递增方式
- IB (increment before) 事先递增方式
- DA (decrement after) 事后递减方式
- DB (decrement before) 事先递减方式
- 指令中寄存器和内存单元的对应关系:
编号低的寄存器对应于内存中低地址单元,编号高的寄存器对应于内存中高地址单元。
当使用IA方式存后需要使用DB方式取(一一对应)
堆栈寻址
- 堆栈是一种数据结构,按先进后出(First In Last Out,FILO)的方式工作,使用一个称作堆栈指针的专用寄存器指示当前的操作位置,
堆栈指针总是指向栈顶。
- 当堆栈指针指向最后压入堆栈的数据时,称为
满堆栈(Full Stack)
,而当堆栈指针指向下一个将要放入数据的空位置时,称为空堆栈(Empty Stack)。
- 同时,根据堆栈的生成方式,又可以分为
递增堆栈(Ascending Stack)
和递减堆栈(Decending Stack)
,当堆栈由低地址向高地址生成时,称为递增堆栈,当堆栈由高地址向低地址生成时,称为递减堆栈
。 - 这样就有四种类型的堆栈工作方式,ARM微处理器支持这四种类型的堆栈工作方式,即:
- 满递增堆栈 (FA):堆栈指针指向最后压入的数据,且由低地址向高地址生成。
- 满递减堆栈(FD) :堆栈指针指向最后压入的数据,且由高地址向低地址生成。
- 空递增堆栈(EA) :堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生成。
- 空递减堆栈(ED) :堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生成。
相对寻址
- 与基址变址寻址方式相类似,相对寻址是基址寻址的一种变通。
相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量
,将两者相加之后得到操作数的有效地址。
BL NEXT ;跳转到子程序NEXT处执行
;跳转地址:PC+NEXT
……
NEXT
……
MOV PC,LR ;从子程序返回