文章目录
(一)Load/Store内存访问指令
是一类可以在ARM寄存器和存储器之间进行数据传递的指令
1. 单寄存器读写操作
指令码
ldr
:把存储器中的一个字(四个字节)装入一个寄存器中
str
:把寄存器中的一个字(四个字节)存储到存储器中
ldrh
:把存储器中的一个半字(两个字节)装入寄存器中
strh
:把寄存器中的一个半字(两个字节)存储到存储器中
ldrb
:把存储器中的一个字节装入一个寄存器中
strb
:把寄存器中的一个字节存储到存储其中
ld:Load
st:Store
r:Register
h:Half
b:Byte
指令格式
ldr/ldrh/ldrb Rd, [Rm]
[Rm]寄存器中额数据将被当作一个地址看待
将[Rm]指向的地址空间的数据存储到Rd寄存器中
str/strh/strb Rn, [Rm]
将Rd寄存器中的数据加载到[Rm]指向的地址空间
使用示例
查看内存中的值
地址的使用
.globl _start
_start:
@将r1存储的数据放到r0指向的地址空间中
ldr r0,=0x40000800 @地址
ldr r1,=0x12345678 @数据
str r1,[r0]
@@@拆分数据
@按字节读取,分别存储在r2,r3,r4,r5寄存器中
ldrb r2,[r0,#0]!
ldrb r3,[r0,#1]!
ldrb r4,[r0,#1]!
ldrb r5,[r0,#1]!
@@@拼接数据
@将各字节左移相应位数,然后用orr拼接
.if 0
lsl r3,r3,#8
lsl r4,r4,#16
lsl r5,r5,#24
orr r6,r6,r2
orr r6,r6,r3
orr r6,r6,r4
orr r6,r6,r5
.else
orr r6,r6,r2,lsl #0
orr r6,r6,r3,lsl #8
orr r6,r6,r4,lsl #16
orr r6,r6,r5,lsl #24
.endif
stop:
b stop
.end
地址偏移
str Rn, [Rm, #offset]
将Rn寄存器中的数据写到[Rm+offset]指向的地址空间中,Rm寄存器中的地址不变
str Rn,[Rm],#offset
将Rn寄存器中的数据写到[Rm]指向的地址空间中,然后更新Rm寄存器中的地址
str Rn,[Rm,#offset]!
将Rn寄存器中的数据写到[Rm+offset]指向的地址空间中,同时更新Rm寄存器中的地址
!:作用是更新Rm寄存器中的地址
- 注:
- ldr/str 偏移地址必须是4的整数倍,可以是负数
- ldrh/strh 偏移地址必须是2的整数倍,可以是负数
- ldrb/strb 偏移地址必须是1的整数倍,可以是负数
2. 栈空间读写操作
栈的分类
增栈:压栈后,
减栈:压栈后,
空栈:当前栈指针指向的栈空间中,没有有效数据,
因此可以先向栈空间中压入新的数据,然后再移动栈指针,指向一个没有有效数据的空间
满栈:当前栈指针指向的栈空间中有有效数据,
需要先移动栈指针指向一个没有有效数据的空间,然后再压栈
栈空间操作方式
满增栈:Full Ascending Stack
stmfa/ldmfa
满减栈:Full Descending Stack
stmfd/ldmfd
空增栈:Empty Ascending Stack
stmea/ldmea
空减栈:Empty Descending Stack
stmed/ldmed
m:multi
满减栈操作指令
ARM处理器默认使用满减栈
ldmfd sp!,{寄存器列表}
sp:栈指针寄存器,存储的是指向的栈空间的地址
!:出栈之后,更新栈指针,栈指针向高地址方向移动
stmfd sp!,{寄存器列表}
寄存器列表的格式要求:
1> 如果寄存器的编号是连续的使用"-“隔开,
2> 如果寄存器的编号不连续使用”,"隔开,
3> 寄存器列表中的寄存器要求从小到大的编号进行书写
4> 不管寄存器列表的寄存器顺序如何书写,永远都是低地址对应小编号的寄存器,高地址对应大编号的寄存器
使用示例
函数多级跳转,保存现场时需要将LR的值也进行保存,否则第二次跳转的LR会覆盖掉第一次跳转时保存的LR值
.globl _start
_start:
ldr sp, =0x40000820 @ 初始化栈指针
mov r0, #0x100
mov r1, #0x200
bl add_func
add r2, r0, r1 @ r2 = r0 + r1 = 0x300
b stop
add_func:
stmfd sp!, {r0-r1,lr} @ 压栈保存现场
mov r0, #0x300
mov r1, #0x400
bl add_func2
add r3, r0, r1 @ r3 = r0 + r1 = 0x700
ldmfd sp!, {r0-r1,lr} @ 出栈恢复现场
mov pc, lr
add_func2:
stmfd sp!, {r0-r1} @ 压栈保存现场
mov r0, #0x500
mov r1, #0x600
add r4, r0, r1 @ r4 = r0 + r1 = 0xB00
ldmfd sp!, {r0-r1} @ 出栈恢复现场
mov pc, lr
stop:
b stop
.end
(二)特殊功能寄存器读写指令
对CPSR寄存器进行读写操作的指令
msr
:将普通寄存器中的数据写到特殊功能寄存器(CPSR)中
mrs
:将特殊功能寄存器(CPSR)中的数据写到普通寄存器中
m:move s:special r:register
msr cpsr,Rn
mrs Rd,cpsr
系统一上电就在SVC模式,切换处理器工作模式,使其处于User模式下
在修改CPSR寄存器的M位时,需保证其他位不变
.globl _start
_start:
.if 1
@方法一:直接使用msr指令,给CPSR寄存器赋值
msr cpsr,#0xD0
.else
@方法二:
mrs r0,cpsr
bic r0,r0,#0x1f @先清零
orr r0,r0,#0x10
msr cpsr,r0
.endif
stop:
b stop
.end
(三)软中断指令
指令码:swi
sw:software
i:interrupt
指令格式
swi{cond} 软中断号