代码改变世界

freertos汇编语言基础知识

2022-01-28 22:03  jym蒟蒻  阅读(184)  评论(0编辑  收藏  举报

汇编语言基础知识

    • 多重存储器访问
    • MRS 和 MSR
    • isb 和 dsb
    • ldr 和 str
    • mov
    • bl 和 bx
    • cps

 

多重存储器访问

在这里插入图片描述

感叹号!表示要自增(Increment)或自减(Decrement)基址寄存器 Rd 的值,时机是在每次访问前(Before)或访问后(After)。增/减,单位:字(4字节)。

Ldr R1,=0x10000000          //传送数据的起始地址0x10000000        

LDMIA R1!,{R0,R4-R6}         //从左到右加载,相当于 LDR R0,10000000  LDR R4,10000004... ...

/*传送后地址加+4,

所以R0=0X10000000地址里的内容,地址加4,

R4=0X10000004地址里的内容,地址加4,

R5=0X10000008地址里的内容,地址加4,

R6=0X1000000C 地址里的内容,地址加4,

由于!,最后的地址写回到R1中,所以R1=0X10000010   */

MRS 和 MSR

这两条指令是访问特殊功能寄存器的“绿色通道”—当然必须在特权级下。

MRS <Rn>, <SReg> ;加载特殊功能寄存器的值到 Rn 
MSR <Sreg>,<Rn> ;存储 Rn 的值到特殊功能寄存器

在这里插入图片描述

指定 PSP 进行更新的例子:

LDR R0, =0x20008000 
MSR PSP, R0 
BX LR ;如果是从异常返回到线程状态,则使用新的 PSP 的值作为栈顶指针

isb 和 dsb

isb:如果某个程序从下一条要执行的指令处更新了自己,但是先前的旧指令已经被预取到流水线中去了,此时就必须清洗流水线,把旧版本的指令洗出去,再预取新版本的指令。因此,必须在被更新代码段的前面使用 ISB,以保证旧的代码从流水线中被清洗出去,不再有机会执行。

DSB:如果把向量表重定位到了RAM中,且这块RAM所在的存储器区域是写缓冲的,向量更新就可能被延迟。为了以防万一,必须在建立完所有向量后追加一条“数据同步隔离(DSB)” 指令,以等待缓冲写入后再继续,从而确保所有数据都已落实。

DSB:如果存储器的映射关系,或者内存保护区的设置可以在运行时更改,就必须在更改之后立即补上一条 DSB 指令(数据同步指令)。因为对 MMU/MPU 的写操作很可能会被放到一个写缓冲中。写缓冲是为了提高存储器的总体访问效率而设的,但它也有副作用,其中之一,就是会导致写内存的指令被延迟几个周期执行,因此对存储器的设置不能即刻生效,这会导致紧临着的下一条指令仍然使用旧的存储器设置。

在这里插入图片描述

ldr 和 str

用于访问存储器的基础指令是“加载(Load)”和“存储(Store)”。

ldr命令:把数据从内存加载到寄存器。

ldr r0, =addr	;r0 = addr
ldr r1, [r0]		; r1 = *r0 r0指向的内容给r1
ldr r1, [r0, #4]	; r1 = *(r0+4)
ldr r1, [r0, #4] !	; r1 = *(r0+4);r0=r0+4;
ldr r1, [r0], #4	; r1 = *(r0);r0=r0+4;

str命令:把数据从寄存器保存到内存。

str r1, [r0]		; *r0 = r1 r1的值作为r0的内容
str r1, [r0, #4]	; *(r0+4) = r1 
str r1, [r0, #4] !	; *(r0+4) = r1;r0=r0+4;
str r1, [r0], #4	; *r0 = r1;r0=r0+4;

在这里插入图片描述

LDR R3, =MY_NUMBER ; R3= MY_NUMBER 
LDR R4, [R3] ; R4= *R3,也就是把R3指向的内容给R4

汇编器通常都支持”LDR Rd, = imm32”伪指令。(LDR内涵挺多)

LDR r0, =0x12345678

mov

MOV 寄存器加载数据,既能用于寄存器间的传输,也能用于加载立即数。

MOV R8,    R3     ;把 R3 的数据传送给 R8
MOV R0, #0x12     ;16位指令 MOV 支持 8 位立即数加载

bl 和 bx

BL 转移并连接。用于呼叫一个子程序,返回地址被存储在 LR 中。

子程呼叫与无条件转移指令:

BL Label ;转移到 Label 处对应的地址,并且把转移前的下条指令地址保存到 LR
BX reg  ;转移到由寄存器 reg 给出的地址

在BX中,reg的最低位指示出在转移后,将进入的状态是ARM(LSB=0)还是Thumb(LSB=1)。 既然 CM3 只在 Thumb 中运行,就必须保证 reg 的 LSB=1。关于bx这个指令,前面中断部分也有讲到。

cps

为了快速地开关中断,CM3 专门设置了 CPS 指令,有 4 种用法:

CPSID I ;PRIMASK=1, ;关中断
CPSIE I ;PRIMASK=0, ;开中断
CPSID F ;FAULTMASK=1, ;关异常
CPSIE F ;FAULTMASK=0 ;开异常