华清远见25072班单片机基础学习day3
重点内容:
跳转指令
指令码
b ----- 有去无回地跳转
bl ----- 有去有回地跳转
指令格式
b/bl 标签名
单寄存器内存读写指令
指令码
str ----- 向内存空间地址中写入4个字节的数据
strh ----- 向内存空间地址中写入2个字节的数据
strb ----- 向内存空间地址中写入1个字节的数据
ldr ----- 从内存空间地址中读取4个字节的数据
ldrh ----- 从内存空间地址中读取2个字节的数据
ldrb ----- 从内存空间地址中读取1个字节的数据
st:store(存储 == 写入)
ld:load(加载 == 读取)
r:register(4个字节)
h:half word(半个字,2个字节)
b:byte(1个字节) 1个word = 1个字 = 4个字节 1个块 = 1个扇区 = 512个字节
指令格式
str/strh/strb Rd, [Rn]
[ ]的作用:在汇编指令中,看到某个寄存器被[ ]包含,就代表这个寄存器中的值为内存空间地址
作用: 将Rn寄存器中的值看作是一片内存空间地址,将Rd寄存器中的值写入4个/2个/1个字节到[Rn]这片内存空间地址中
ldr/ldrh/ldrb Rd, [Rn]
作用: 将Rn寄存器中的值看作是一片内存空间地址,从[Rn]这片内存空间地址中读取4个/2个/1个字节的数据到Rd寄存器中
内存地址
并不是所有的内存地址都可以被用户直接使用
内存地址存在读写权限,可读权限的内存地址用户可以从其中读取数据、可写权限的内存地址用户可以向其中写入数据
除了用户可以操作的内存地址外,还有很多只有系统/CPU才可以访问的内存地址,此时用户无法访问
如果访问,就是非法访问/使用内存空间地址,此时会报错
地址偏移
ldr Rd, [Rn, #offset]
含义:
#offset就是一个值,就是内存空间地址的偏移量
将Rn + #offset的值看作是一片内存空间地址
从Rn + #offset这片内存空间地址中读取4个字节的数据到Rd寄存器中
注意:Rn寄存器中的值不会改变
ldr Rd, [Rn], #offset
含义:
将Rn中的值看作是一片内存空间地址
从Rn这片内存空间地址中读取4个字节的数据到Rd寄存器中
注意:当读取完数据后,Rn寄存器中的值发生改变,Rn = Rn + #offset
ldr Rd, [Rn, #offset]!
含义:
!的作用:更新内存空间地址(Rn中的值)
将Rn + #offset的值看作是一片内存空间地址
从Rn + #offset这片内存空间地址中读取4个字节的数据到Rd寄存器中
注意:当读取完数据后,Rn寄存器中的值发生改变,Rn = Rn + #offset
总结注意事项:
1、#offset就是一个值,就是内存空间地址的偏移量
2、ldr/ldrh/ldrb 和 str/strh/strb 都使用以上格式编写
3、使用ldr/str进行地址偏移的内存读写操作时,#offset偏移量的值必须要是4的倍数
4、使用ldrh/strh进行地址偏移的内存读写操作时,#offset偏移量的值必须要是2的倍数
5、使用ldrb/strb进行地址偏移的内存读写操作时,#offset偏移量的值必须要是1的倍数
栈指针寄存器读写指令
栈的分类
增栈:当进行压栈操作时,栈指针向高地址方向移动(栈指针寄存器中的值增大) 当进行出栈操作时,栈指针向低地址方向移动
减栈:当进行压栈操作hi,栈指针向低地址方向移动(栈指针寄存器中的值减小) 当进行出栈操作时,栈指针向高地址方向移动
满栈:认为当前栈指针指向的内存地址中存在有效数据 如果想要进行压栈操作,需要先移动栈指针的指向,指向一片没有有效数据的地址,再进行压栈操作
空栈:认为当前栈指针指向的内存地址中没有有效数据 如果想要进行压栈操作,直接进行压栈操作即可
压栈:就是向栈空间中某片地址中写入数据
出栈:就是从栈空间中某片地址中读取数据
实际栈的分类:
1、满减栈(Full Descending Stack) -----------> ARM架构使用的是满减栈
2、满增栈(Full Ascending Stack)
3、空减栈(Empty Descending Stack)
4、空增栈(Empty Ascending Stack)
指令码
满减栈(Full Descending Stack) -----------> stmfd/ldmfd
满增栈(Full Ascending Stack) -----------> stmfa/ldmfa
空减栈(Empty Descending Stack) -----------> stmed/ldmed
空增栈(Empty Ascending Stack) -----------> stmea/ldmea
st:store(存储 == 写入数据)
ld:load(加载 == 读取数据)
m:multiple(多个、多种)
指令格式(以满减栈为例)
stmfd sp!, {寄存器列表}
含义:
将寄存器列表中的值写入到sp栈指针寄存器中保存的内存地址空间中
!的作用:用于更新内存空间地址(SP寄存器中的值减小)
由于使用的是满减栈(栈指针的指向先向低地址方向移动,再压入数据)
SP = 0x40000820,此时需要压入16个字节的数据 SP = 0x40000820 - 0xf = 0x40000810
16个字节的数据的地址范围:0x40000810 - 0x40000820
ldmfd sp!, {寄存器列表}
含义:
将SP栈指针寄存器中保存的内存地址中的数据读取到寄存器列表中
!的作用:用于更新内存空间地址(SP寄存器中的值增大)
寄存器列表注意事项:
1、寄存器列表中用于存放多个寄存器,使用{}进行包含
2、寄存器列表中的寄存器标号没有大小写区分
3、如果寄存器列表中的寄存器编号是连续的,使用-进行分隔 如{r0-r5}
4、如果寄存器列表中的寄存器编号是不连续的,使用,进行分隔 如{r5, r8}
5、寄存器列表中的寄存器编号一般采用从小到大的方式编写 如{r0-r2, r4, r9} 也可以从大到小的方式编写,但是此时只能使用,进行分隔 如{r4, r3, r2, r1}
CPSR特殊功能寄存器读写指令
指令码
msr ------ 向CPSR寄存器中写入数据
mrs ------ 从CPSR寄存器中读取数据
CPSR特殊功能寄存器只能通过msr和mrs进行访问,其他不同汇编指令无法直接操作CPSR寄存器
指令格式
msr CPSR, oprand_shifter2
含义:将oprand_shifter2第二操作数的值写入到CPSR寄存器中
mrs Rd, CPSR
含义:从CPSR寄存器中读取数据到Rd寄存器中
swi软中断指令
指令码:swi sw:software i:interrupt 指令格式:swi 软中断号(数字)
作用:不管当前处于CPU什么工作模式下,当执行软中断指令后,立刻切换到SVC模式下
