求ARM汇编 BX LR 结果


PendSV_Handler
    CPSID   I
    MRS     R0, PSP
    CBZ     R0, PendSV_Handler_Nosave ;compare and branch if zero.

    SUBS    R0, R0, #0x20
    STM     R0, {R4-R11}

    LDR     R1, =OSTCBCur
    LDR     R1, [R1]
    STR     R0, [R1]


PendSV_Handler_Nosave
    PUSH    {R14}
    LDR     R0, =OSTaskSwHook
    BLX     R0
    POP     {R14}

    LDR     R0, =OSPrioCur
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCur
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]

    LDR     R0, [R2]
    LDM     R0, {R4-R11}
    ADDS    R0, R0, #0x20
    MSR     PSP, R0
    ORR     LR, LR, #0x04
    CPSIE   I
    BX      LR

这是将 uc/OS-II 移植到 STM32F103,os_cpu_a.asm 中的一段
第4行如果PSP==0,那么就会跳转到 PendSV_Handler_Nosave
我想知道,PendSV_Handler_Nosave 完了之后会返回到第5行继续吗?
它末尾不是有一个 BX LR 么?不理解这个 BX LR 是什么意思

谢谢~

还有,末尾有条注释,

ORR LR, LR, #0x04 ;将 0xFFFFFF(E/F)(9/D) 变成 0xFFFFFF(E/F)D,返回线程模式,并使用线程堆栈

LR 是什么时候变成 0xFFFFFF(E/F)(9/D) 的,它不应该保存返回的偏移地址吗?
线程堆栈,以及 0xFFFFFF(E/F)(9/D) 代表什么我是知道的,但是 LR 是什么时候变的?自动完成的吗?


啊我明白了。有些复杂。
简单回答是:不会返回到第5行,而是退出中断,变为线程模式(只有中断的时候才是 Handler 模式),并使用线程堆栈;LR 是进到中断的时候自动改变的,变成了一个比较特殊的值 EXC_RETURN,而不是某个具体的地址。

https://blog.csdn.net/weixin_45217215/article/details/128661187

img


img


img


PendSV_Handler
    CPSID   I
    MRS     R0, PSP
    ;跳转后就与 PendSV_Handler 无关了
    ;B 是无条件跳转,不会保存返回地址 LR
    ;CBZ 只是多了个条件,同样不会保存返回地址 LR
    CBZ     R0, PendSV_Handler_Nosave ;compare and branch if zero

    SUBS    R0, R0, #0x20
    STM     R0, {R4-R11}

    LDR     R1, =OSTCBCur
    LDR     R1, [R1]
    STR     R0, [R1]


PendSV_Handler_Nosave
    PUSH    {R14}
    LDR     R0, =OSTaskSwHook
    BLX     R0
    POP     {R14}

    LDR     R0, =OSPrioCur
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCur
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]
    ;是STRB,不是STR,因为 OSPrioCur 和 OSPrioHighRdy 都是字节类型
    LDR     R0, =OSPrioCur ;OSPrioCur = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCur ;OSTCBCur  = OSTCBHighRdy;
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]
    
    LDR     R0, [R2] ;R2 = OSTCBHighRdy;R0 = *OSTCBHighRdy = OSTCBHighRdy->OSTCBStkPtr
    LDM     R0, {R4-R11} ;Restore r4-11 from new process stack; R0不变
    ADDS    R0, R0, #0x20 ;出栈后,栈指针增加32;32字节 = 8个要“出栈”的寄存器 * 每个寄存器4字节
    MSR     PSP, R0 ;Load PSP with new process SP
    ;0xFFFFFF(E/F)9 变成 0xFFFFFF(E/F)D,原来是 0xFFFFFF(E/F)D 就不变。返回线程模式,并使用线程堆栈(SP=PSP)
    ;参考权威指南 表9.3、表9.4
    ORR     LR, LR, #0x04 ;Ensure exception return uses process stack
    CPSIE   I ;开中断
    ;返回。由于 PendSV 是最低优先级别的,所以肯定不是返回到另一个中断,而是到线程模式
    ;就像上面说的,是 0xFFFFFF(E/F)9 或 0xFFFFFF(E/F)D,不可能是 0xFFFFFF(E/F)1
    ;反正知道有这么回事,知道这个函数大概是干什么的,就行了
    BX      LR

BX LR 指令表示将程序控制权返回到存储在LR寄存器中的地址处,同时会清除当前的中断标志。用于退出子程序或中断服务例程。