原文:http://blog.sina.com.cn/s/blog_87c063060101ber5.html
在嵌入式开发中,汇编程序常常用于非常关键的地方,比如系统启动时的初始化,进出中断时的环境保存、恢复,对性能要求非常苛刻的函数等。
条件码(cond)
助记符
含义
cpsr中条件标志位
0000
eq
相等
Z = 1
0001
ne
不相等
Z = 0
0010
cs/hs
无符号数大于/等于
C = 1
0011
cc/lo
无符号数小于
C = 0
0100
mi
负数
N = 1
0101
pl
非负数
N = 0
0110
vs
上溢出
V = 1
0111
vc
没有上溢出
V = 0
1000
hi
无符号数大于
C = 1 或 Z = 0
1001
ls
无符号数小于等于
C = 0 或 Z = 1
1010
ge
带符号数大于等于
N = 1, V = 1 或 N = 0, V = 0
1011
lt
带符号数小于
N = 1, V = 0 或 N = 0, V = 1
1100
gt
带符号数大于
Z = 0 且 N = V
1101
le
带符号数小于/等于
Z = 1 或 N! = V
1110
al
无条件执行
-
1111
nv
从不执行
-
1、相对跳转指令: b 、 bl
不同之处在于: bl 指令除了跳转之外,还将返回地址( bl 的下一条指令的地址)保存在 lr 寄存器中。
跳转范围:当前指令的前后32M。
它们是与位置无关的指令。
示例:
......
fun1:
......
fun2:
......
2、数据传送指令: mov ,地址读取伪指令: ldr
mov 指令可以把一个寄存器的值赋给另一个寄存器,或者把一个常数赋给寄存器。
例:
mov
mov
mov 指令传送的常数必须能用立即数来表示。
当不知道一个数能否用立即数来表示时,可以使用 ldr 命令来赋值。 ldr 是伪指令,它不是真实存在的指令,编译器会把它扩展成真正的指令:如果该常数能用立即数来表示,则使用 mov 指令;否则编译时将该常数保存在某个位置,使用内存读取指令把它读出来。
例:
ldr
ldr 本意为“大范围的地址读取伪指令”,以下是获得代码的绝对地址:
例:
label:
......
3、内存访问指令: ldr 、 str 、 ldm 、 stm
ldr 指令既可能是大范围的地址读取伪指令,也可能是内存访问指令。当它的第二个参数前面有 “
= ”时,表示伪指令,否则表示内存访问指令。
ldr 指令是从内存中读取数据到寄存器,str 指令把寄存器的值存储到内存中,它们操作的数据都是32位的。
例:
ldr
ldr
ldr
str
str
str
ldm 和 stm 属于批量内存访问指令,只用一条指令就可以读写多个数据。格式为:
ldm
stm
其中,{cond} 表示指令的执行条件有:
大多数ARM指令都可以条件执行,即根据cpsr寄存器中的条件标志位决定是否执行该指令:如果条件不满足,该指令相当于一条nop指令。
每条ARM指令包含4位的条件码域,这表明可以定义16个执行条件。
cpsr条件标志位N、Z、C、V分别表示Negative、Zero、Carry、oVerflow。
表示地址变化模式,有4种方式:
ia (Increment After)
ib (Increment Before)
da (Decrement After)
db (Decrement Before)
中保存内存的地址,如果后面加上感叹号,指令执行后,rn 的值会更新,等于下一个内存单元的地址。
表示寄存器列表,对于 ldm 指令,从
所对应的内存块中取出数据,写入这些寄存器;对于 stm 指令,把这些寄存器的值写入
所对应的内存块中。
{^} 有两种含义:
如果 中有 pc寄存器 ,它表示指令执行后,spsr寄存器的值将自动复制到cpsr寄存器中——这常用于从中断处理函数中返回;
如果 中没有 pc寄存器 , {^} 表示操作的是用户模式下的寄存器,而不是当前特权模式的寄存器。
例:
HandleIRQ: