ARM常用汇编指令

1、数据操作指令

数据搬移指令

mov:移动指令
mvn:取反移动指令
语法格式:{cond}{s} {Rd}, {oprand2}

mov r0, #0xFF   		// 立即数0xFF放入寄存器r0  立即数前需要加“#”
mov r1, r0      		// 将寄存器r0的数据放入寄存器r1中
mvn r2, #0xFF   		// r2 = ~0xFF(0xFFFFFF00)
mov r3, #0xFFFFFF		// 0xFFFFFF是有效数,写入机器码会转换成立即数#~0xFF000000
mov r0, #0xFF000000
ldr r0, =0x12345678   	//ldr伪指令 将0x12345678 放入寄存器r0
算数运算指令

{cond}{s} {Rd}, {Rn}, {oprand2}
add :普通的加法指令
adc :带进位的加法指令
sub :普通的减法指令
sbc :带借位的减法指令
练习题1
两个64位的数相加
第一个64位的数高32位在R1,低32位在R0
第二个64位的数高32位在R3,低32位在R2
结果高32位在R5,低32位在R4

mov r0, #0xFFFFFFFE
mov r1, #0x3
mov r2, #0x4
mov r3, #0x5
adds r4, r0, r2   @ r4 = r0 + r2		// s:产生进位C位置1,否则为0
adc r5, r1, r3   @ r5 = r1 + r3 + C		// adc指令自动判断C位的值

将R0寄存器中的第[4]位清0的三种方法,保证其他位不变

and r0, r0, #0xFFFFFFEF
and r0, r0, #(~0X10)
and r0, r0, #(~(0x1 << 4))
/*and r0, #0x10000 如果目标寄存器和第一个操作寄存器编号相同,可以合并写一个。*/

练习题2
两个64位的数减法
第一个64位的数高32位在R1,低32位在R0
第二个64位的数高32位在R3,低32位在R2
结果高32位在R5,低32位在R4

mov r0, #0xFFFFFFFE
mov r1, #0x3
mov r2, #0x4
mov r3, #0x5
subs r4, r2, r0 @r4 = r2 - r0
sbc r5, r3, r1	@r5 = r3 - r1 - N
乘法指令测试
mov r0, #3
mov R1, #4
mul r2, r0, r1   //r2 = r0 * r1
// 第二个操作数只能是寄存器,不能是立即数
// mul r2, r0, #4    @ error
mul r0, r1		//r0 = r0 * r1
逻辑运算指令

and:与
orr :或
eor :异或
练习:
使用位运算符 : & | ^ ~ << >>
1、将R0寄存器中的第[4]位清0,保证其他位不变

and r0, r0, #0xFFFFFFEF
and r0, r0, #(~0X10)
and r0, r0, #(~(0x1 << 4))
/*and r0, #0x10000 如果目标寄存器和第一个操作寄存器编号相同,可以合并写一个。*/

2、将R0寄存器中的第[20]位置1,保证其他位不变

orr r0, r0, #(~(0x1 << 20))

3、将R0寄存器中的第[11:8]位置1,保证其他位不变

orr r0, r0, #(0xF << 8)

4、将R0寄存器中的第[3:0]位清0,保证其他位不变

	and r0, r0, #0xFFFFFFF0

5、将R0寄存器中的第[29:26]位写成1010,保证其他位不变

and r0, r0, #(~(0xF << 26))		@先清零
orr r0, r0, #(0xA << 26)		@再置1

6、将R0寄存器中的第[30:25]位写成101010,保证其他位不变

and r0, r0, #(~(0x3F << 25))		@先清零
orr r0, r0, #(0x2A << 25)			@再置1

2、跳转指令 b bl

b :跳转、不保存返回地址到lr寄存器中
bl:跳转、自动保存返回地址到lr中
语法格式: b/bl{cond} Label
Label:
  汇编代码
跳转指令的本质:修改PC值

// b 不保存返回地址到lr寄存器中
	.if 0
	mov r0, #3
	mov r1, #4
	b func_add		//跳转到func_add 不保存rl 没办法返回
	add r2, r0, r1
	b stop
	
func_add:
	mov r4, #5
	mov r5, #6
	add r6, r4, r5
//bl 自动保存返回地址到lr中
	mov r0, #3
	mov r1, #4
	bl func_add
	add r2, r0, r1
	b stop
	
func_add:
	mov r4, #5
	mov r5, #6
	add r6, r4, r5
	mov pc, lr

3、load/store指令(单/多寄存器操作)

1、单寄存器操作指令
将Rn指向的内存空间中的数据读到Rm寄存器中,读4字节
Rn寄存器中的值,看成内存的地址。
ldr{code} Rm, [Rn]

将Rm寄存器中的数据写到Rn指向的内存空间中,写4字节
Rn寄存器中的值,看成内存的地址。
str{code} Rm, [Rn]

ldr r0, =0x40000800
ldr r1, =0x12345678
str r1, [r0]		//在0x40000000地址写入数据0x12345678
ldr r2, [r0]		//将0x40000000地址的数据0x12345678写入寄存器r2
ldr r0, =0x40000800
ldr r1, =0x11111111
ldr r2, =0x22222222
ldr r3, =0x33333333
//将R1中的值存到R0+4指向的地址空间中,R0中的值不变
str r1, [r0, #4]  //前索引
//将R2中的值存到R0指向的地址空间中,R0=R0+4
str r2, [r0], #4  //后索引
//将R3中的值存到R0+4指向的地址空间中,R0=R0+4
str r3, [r0, #4]! //自索引
@ 注:立即数要求是4的整数倍
@ 以上索引方式同样适用于ldr指令

@ ldrb/strb/ldrh/strh   b : byte  h : half
@ 语法格式跟ldr和str完全一致。

多寄存器操作指令
从Rm指向的地址空间中读连续的数据到寄存器列表中,
ldm Rm, {寄存器列表}

将寄存器列表中的数据写到Rm指向的连续的内存空间中。
stm Rm, {寄存器列表}
要求:
@ 寄存器列表
1》 寄存器的编号要求从小到大
2》 寄存器连续使用“-”隔开
3》 寄存器不连续使用“,”隔开

ldr r0, =0x40000800
ldr r1, =0x11111111
ldr r2, =0x22222222
ldr r3, =0x33333333
ldr r4, =0x44444444
ldr r5, =0x55555555
//stm r0, {r1-r5}
stm r0, {r5,r4,r3,r2,r1}
//stm r0, {r1-r3,r4,r5}
//ldm r0, {r6-r10}
ldm r0, {r10,r9,r8,r7,r6}
@ 总结:寄存器列表中的寄存器顺序不管怎样,
@ 	永远都是低地址对应小编号寄存器
@ 	高地址对应大编号的寄存器

4、特殊功能寄存器传送指令 msr mrs

将普通寄存器(立即数)中的数据写到cpsr中
msr{cond} cpsr, rn
msr{cond} cpsr, #shift

将cpsr寄存器中的值读到普通寄存器中
mrs rn, cpsr

例子:从SVC模式切换到user模式
第一种方式

msr cpsr,#0xD0
mov r0, #0xD0
msr cpsr, r0

第二种方式

mrs r0, cpsr
bic r0, r0, #0x1F
//and r0, r0, #(~0x1F)
orr r0, r0, #0x10
msr cpsr, r0

5、软中断指令 swi

/******************************/
//构建异常向量表
b reset
b undef_handler	
b swi_handler
b pref_handler
b data_handler
b .
b irq_handler
b fiq_handler
			
reset: 
	//初始化svc模式下的栈
	ldr sp, =0x40000800		//此处的sp是svc模式下的栈指针
	//从SVC模式切换到用户模式
	mrs r0, cpsr
	bic r0, r0, #0x1F
	orr r0, r0, #0x10
	msr cpsr, r0
	//初始化用户模式下的栈
	ldr sp, =0x40000900		//此处的user是svc模式下的栈指针
	
	//开始执行代码
	mov r0, #3
	mov r1, #4
	swi 2		//软中断指令
	swi 3		//软中断指令
	add r2, r0, r1   //r2 = r0 + r1 = 0x7
	b stop
	
//死循环
stop:
	bstop
	
//软中断的异常处理程序
swi_handler:
	//保存现场
	stmfd sp!, {r0-r1,lr}
	//获取软中断号
	sub r3, lr, #4
	ldr r4, [r3]
	bic r4, r4, #0xFF000000
	//对软中断号进行判断,执行分支程序
	cmp r4, #2
	moveq r0, #5
	cmp r4, #3
	moveq r1, #6
	//恢复现场 
	//^:恢复spsr_<mode>到cpsr中
	ldmfd sp!, {r0-r1,pc}^
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值