首先,在前面已经将ARM架构体系和计算机系统的简单讲解,如果到时候忘了直接先浏览一下前面写好的《从计算机系统组成到ARM体系架构》。
处理器执行状态
最常用的执行状态ARM状态,其次是Thumb状态,除此之外还有ThumbEE状态,和Jazelle状态(不同状态有各自不同的指令集);关于这四个状态,在前面CPSR寄存器部分有详细描述
从ARM切换到Thumb状态
下面是一个从ARM切换到Thumb状态,再从Thumb状态切换到ARM状态的例子:
.text
mov r3,#6 @PC=0x00000000 这句不是必须的
adr r0,thumb @pc=0x00000004 伪指令真正的汇编指令是:add r0,pc,0x4,这里的PC+0x4=Thumb的地址即=0x00000010,这里的PC是一个特别的值
add r0,r0,#1 @pc=0x00000008 想要切换到Thumb状态需要让指定转跳的地址最后一位为1
bx r0 @pc=0x0000000c 转跳到thumb,即切换为Thumb状态,bx和bl是有区别的,bx可以切换状态,CPSR的状态会改变
.code 16 @ 即指定步长为0x2,16位地址每次偏移2个字节
thumb:
mov r3,#4 @pc=0x00000010 这句不是必须的
ldr r3,=ARM @pc=0x00000012 真正的汇编指令:LDR r3,[pc,#0xc] 即ARM的地址0x00000018
bx r3 @pc=0x00000014 转跳到ARM,即切换为ARM状态,因为转跳地址最后一位不是1;同时CPSR寄存器的值会改变
.code 32 @ 即指定步长为0x4,32位地址每次偏移4字节
ARM:
mov r3,#2 @pc=0x00000018 这句不是必须的
mov r3,#4 @pc=0x0000001c 这句不是必须的
.end
ARM执行状态和Thumb执行状态对比
ARM | Tumb |
---|---|
32位的代码密度,代码量更大 | 16位的代码密度,代码量更小 |
执行效率更高 | 执行效率更低 |
完整的体系结构,可以执行异常 | 不是完整的体系结构,想要执行异常需要切换到ARM状态,只支持通用功能 |
ARM指令集 | Thumb指令集,这两个指令集有区别,具体差异可以百度 |
ARM常见指令集
mov数据传输指令
mov 寄存器,立即数或寄存器
mov r1,#3 相当于r1=3;格式#?中?是立即数,立即数合法的条件(1)最高位1和最低位1之间二进制数的个数小于等于8合法;(2)如果最高位和最低位1之间二进制数的个数大于8,那么循环右移再判断,如果仍然大于8,那么不合法;
mvn 取反传送指令
mvn 寄存器1,立即数或者寄存器2
mvn r1,#3 相当于r1=0xFFFFFFFC
LDR数据传输(伪指令)
LDR 寄存器,=数字
LDR r1,=0x124242 相当于r1=124242,使用LDR不用考虑数字是否合法的问题,这个指令非常,非常好用且常用
add 加法指令
add 寄存器1,寄存器1,立即数或者寄存器2
ldr r1,=3
add r1,r1,#4 结果r1=3,r1=r1+4;最后r1=7;
这里其实暴露了一个问题:还是立即数的问题;我认为最好的解决办法是这样写
ldr r1,=3
ldr r2,=4
add r1,r1,r2
adds能改变CPSR寄存器C的加法运算,adc带进位的加法运算
如果指令后面带S,那么这个指令具备改变CPSR的能力
adds 寄存器1,寄存器1,寄存器或立即数2
adc 寄存器1,寄存器1,寄存器2或立即数
下面是使用add和adc的例子
.text
ldr r1,=0xFFFFFFFC @r1=0xFFFFFFFC
adds r3,r1,#0x8 @r3=0x4,cpsr寄存器的C位置1
ldr r3,=5 @r3=3
adc r4,r3,#3 @r4=r3+3+(寄存器CPSR的)c,即r4=3+5+1
.end
sub减法指令,subs能改变CPSR寄存器N,C的寄存器的减法,sbc带进位的减法
sub 寄存器1,寄存器1,寄存器2或立即数
aubs 寄存器1,寄存器1,寄存器2或立即数
sbc 寄存器1,寄存器1,寄存器2或立即数
sub太简单就不举例了,下面举例subs和sbc的使用
.text
ldr r1,=0X1 @r1=0x1
ldr r2,=0XFF @r2=0xFF
ldr r4,=0x2 @r4=0x2
ldr r5,=0x3 @r5=0x3
subs r3,r2,r1 @r3=r2-r1,CPSR的中的C=1
sbc r6,r4,r5 @r6=r4-r5-!c 即r6=2-3-0=0xFFFFFFFF
subs r3,r1,r2 @r3=r1-r2,CPSR中N=1,C=0;
sbc r6,r4,r5 @r6=r4-r5-!c 即r6=2-3-1=0xFFFFFFFE
.end
前面已经说过了一般来说指令后面加s后缀会改变CPSR
mul乘法指令(无符号),muls有符号的乘法指令(即能改变CPSR的N位),mla加乘指令
mul 寄存器1,寄存器1,寄存器2 即寄存器1中存放的值=寄存器中存放的值1*寄存器中存放的值
muls 寄存器1,寄存器1,寄存器2 和mul一样,区别在于会改变CPSR的N位
mla 寄存器1,寄存器1,寄存器2,寄存器3 即寄存器1中存放的值=(寄存器1中存放的值*寄存器2中存放的值)+寄存器3中存放的值
.text
ldr r1,