ARM汇编指令集
一、汇编语言介绍
1. 概念
指的是用助记符代替操作码,用地址符号或标签(:#&)代替地址码的编程语言。
2. 优缺点
优点:可以直接访问硬件目标,代码简短,执行速度快
缺点:可移植性差,可阅读性差
3. ARM指令集特点
- 指令码长度固定如:32bit。
- 几乎所有指令都是有条件执行
- 寄存器与内存之间交换数据采用专用指令集
二、指令格式
CPSR寄存器:当前程序状态寄存器,记录当前CPU运行状态,最高的四位记录当前指令执行的结果。
S:决定当前指令的结果是否需要更新CPSR寄存器。
Rn: r0 r1或立即数,都可带移位运算符。
1. 立即数的编码规则
立即数最多只能占一条ARM指令的12位
例如0x2000 0000 占32位,
循环向左移动偶数位使其能在低八位表示,变成0x2,移动了四位。为什么是偶数位,因为第8-11位要将移动的位数除以2保存起来。
系统在使用时会将0x2循环向右移动第8-11位保存的位数*2,这样又还原成了0x2000 0000。
2. Keil5汇编
keil5汇编程序示例
area mycode,code,readonly
code32
entry
start
mov r0,#1
end
area:代码存放区域
mycode:说明区域名称
code:说明区域中存放的东西为代码
readonly:说明内容为只读
code32:32位的指令
以上都为编译器的伪指令。
验证对立即数的操作
area mycode,code,readonly
code32
entry
start
mov r0,#1
mov r1,#0x20000000
end
可以看到,立即数占12位,最高四位为2,即上面说的循环左移四位除以2,低八位为左移后的数,即0x2。
三、数据传送指令
1. mov mvn 使用示例
area mycode,code,readonly
code32
entry
start
mov r0, #0x1
mov r1, #0x20000000
mov r2, r1
mvn r3, #0xff
mvn r4, r3
end
2. ldr指令对非立即数的操作
ldr r5, =0x20008000
伪指令:编译器在编译的时候把伪指令分解成几条指令实现
操作流程:
1.首先放到一个地址空间中 如:0x10000000=0x20008000
2.再通过mov指令将合法立即数0x10000000放到某个寄存器
3.最后通过ldr指令去这个地址将里面的内容取出来
3. 往寄存器中存放数据的方式
1.mov 有效的立即数
2.mvn 立即数的按位取反的数
3.ldr 任何数**
4. add sub mul 使用示例
area mycode,code,readonly
code32
entry
start
mov r0 ,#3
add r0, r0, #4
mov r1, #1
add r0, r0, r1
sub r0, r0, #2
mul r2, r0, r1
end
四、数据运算指令(位运算)
1. orr and bic 示例
area mycode,code,readonly
code32
entry
start
mov r0, #0x10
orr r0, r0, #0x1 ;0x11
and r1, r0, #0x10 ;0x10
bic r2, r1, #0x1 ;0x10&~0x1=0x10
end
2. 按需置1清零用法
五、内存操作指令
1. swp使用示例
area mycode,code,readonly
code32
entry
start
mov r0, #0x99
mov r1, #0x11
mov r2, #0x40000000
swp r0, r1, [r2]
end
2. ldr str使用示例
area mycode,code,readonly
code32
entry
start
mov r0, #0x40000000
mov r1, #0x99
str r1, [r0] ;把r1存储到r0指向的内存地址中
ldr r2, [r0]
end
3. str连续存储
简单粗暴法:
area mycode,code,readonly
code32
entry
start
mov r0, #0x40000000
mov r1, #0x1
mov r2, #0x2
mov r3, #0x3
mov r4, #0x4
str r1, [r0]
add r0, r0, #4 ;地址加4
str r2, [r0]
add r0, r0, #4 ;地址加4
str r3, [r0]
add r0, r0, #4 ;地址加4
str r4, [r0]
end
衍生用法:
area mycode,code,readonly
code32
entry
start
mov r0, #0x40000000
mov r1, #0x1
mov r2, #0x2
mov r3, #0x3
mov r4, #0x4
str r1, [r0], #4
str r2, [r0], #4
str r3, [r0], #4
str r4, [r0], #4
ldr r5, [r0], #-4
ldr r6, [r0], #-4
ldr r7, [r0], #-4
ldr r8, [r0], #-4
end
4. ldmfd stmfd 指令
area mycode,code,readonly
code32
entry
start
ldr r0, =0x40000100
mov r1, #0x1
mov r2, #0x2
mov r3, #0x3
mov r4, #0x4
stmfd r0!, {r1-r4}
ldmfd r0!, {r5-r8}
end
stmfd 原本是先减4 ,再存储,但r0不变,加上!后,r0会先减4,再存储。
ldmfd 加上!后,先加载r0指向的数据,r0再加4。
应用场景:中断现场的数据保存
六、 跳转指令
apcs:规定sp指向内存地址空间,lr专门用于备份pc
1. b指令跳转并返回示例
area mycode,code,readonly
code32
entry
start
mov r0, #0x1
mov lr, pc ;当改指令正在执行时
b func1 ;已被译码
mov r2, #0x2 ;pc指向
func1
mov r1,#0x2
mov pc, lr ;函数返回
loop
b loop
end
2. bl指令版本
area mycode,code,readonly
code32
entry
start
mov r0, #0x1
bl func1
mov r2, #0x2 ;pc指向
func1
mov r1,#0x2
mov pc, lr ;函数返回
loop
b loop
end
PS:bl func1中的func1 不是绝对地址,是相对当前指令的偏移量,系统给了32bit中的24bit表示,跳转范围:±32MB
那如何实现长跳转?答:直接修改PC寄存器,即绝对跳转