槑++ 2023-03-30 13:46 采纳率: 86.7%
浏览 35
已结题

求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 是什么意思

谢谢~

  • 写回答

2条回答 默认 最新

  • 槑++ 2023-03-30 14:17
    关注

    还有,末尾有条注释,

    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
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月31日
  • 已采纳回答 3月30日
  • 创建了问题 3月30日

悬赏问题

  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan