LDR与LDR伪指令解析与使用场景
下面是freertos源码中使用LDR命令一些场景
LDR指令使用场景1:
/*ulPortInterruptNestingConst = ulPortInterruptNestingConst +1*/
LDR r3, ulPortInterruptNestingConst /*获取ulPortInterruptNestingConst位置的内容,即ulPortInterruptNesting变量对应的地址。所以如果访问ulPortInterruptNesting,需要LDR r1, [r3] 才会将ulPortInterruptNesting的内容加载到r1寄存器*/
LDR r1, [r3]
ADD r4, r1, #1
STR r4, [r3]
ulPortInterruptNestingConst: .word ulPortInterruptNesting
uint32_t ulPortInterruptNesting = 0UL; //此变量在某个c文件中定义
LDR指令使用场景2:
/* Call the interrupt handler. */
PUSH {r0-r4, lr}
LDR r1, vApplicationIRQHandlerConst /*获取vApplicationIRQHandlerConst位置的内容,即HwiP_irq_handler_c,因为HwiP_irq_handler_c本身就是一个中断处理函数地址,所有能够使用 blx r1直接跳转到函数地址*/
BLX r1
POP {r0-r4, lr}
ADD sp, sp, r2
vApplicationIRQHandlerConst: .word HwiP_irq_handler_c
LDR
伪指令主要有两种用途:
1.加载32位常量到寄存器:LDR R0, =0x1234ABCD ; 将32位立即数加载到R0,汇编器会自动将该指令转换为合适的MOV
或PC相对加载
指令。
2.加载标号地址:LDR R1, =data_label ; 将编译器给这个data_label标号的地址加载到R1
总结
LDR r1, [r3] /*这条指令将ulPortInterruptNesting指针本身的内容放入r1中*/
LDR r2, [r1] /*那么这条指令就是ulPortInterruptNesting指针指向的内容放入r2,即*ulPortInterruptNesting */
LDR r3, [r2] /*如果ulPortInterruptNesting是一个二级指针,那么现在r3中的内容就是**ulPortInterruptNesting */
以此类推 n级指针都可以访问