一文看懂LR寄存器及 BX LR 指令的两种用途

本文解析了ARM架构中LR寄存器在普通函数调用与异常处理中的不同作用。通过对比函数返回与异常返回场景,解释了LR寄存器如何控制程序流程与堆栈切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一文看懂LR寄存器

 

 

 

 

不知你在DEBUG程序,又或者阅读操作系统源码时候有没细心观察,从一个普通子函数返回与异常(中断)返回的汇编指令都是BX  LR,但是这两者的意义是一样的吗?这篇文章就来揭开LR寄存器的神秘面纱。

当单片机涉及函数跳转或者任务调度的时候,理解MCU如何处理堆栈与改变各个通用寄存器的状态尤为重要,下面就来比较一下在不同情况下LR寄存器的意义。

上图是一个简单的例子,当仿真点击“下一步”的时候,MCU就会执行BX LR指令,并且从aa子函数返回到main函数中,可以看到在普通子函数里执行BX  LR的意义是“跳转到LR寄存器里的地址执行”。

对比一下一段ucos的源码,如果对M3内核有所了解的小伙伴一定知道堆栈为什么是这样定义的,那么这时候我们发现OS_TaskReturn是作为一个错误返回函数,并且赋值到堆栈中R14(LR)相应的位置。

任务调度函数会将PSP堆栈指针指向我们定义自定义的堆栈,然后最后一句汇编是BX LR,那么按照普通子函数执行BX LR的意义,这个时候MCU是会运行OS_TaskReturn这个函数吗?这样不就进入错误函数了吗?

其实不然,因为用M系列实现ucos的任务调度是在PendSV异常(中断)里面实现的,而在异常(中断)里的LR寄存器不再是普通函数里面“返回地址”的意义,而是一个定义为一个称作exc-return的值,当执行BX  LR时候,这个值决定了MCU退出异常(中断)之后的运行等级是在特权级还是用户级以及用的堆栈是MSP还是PSP,而MCU即将要执行的是从PSP堆栈中POP出来的p_task函数,而不是OS_TaskReturn函数。

### 小型实时操作系统(RTOS)汇编代码与教程 #### 汇编代码实例 对于小型实时操作系统的实现,通常会涉及到底层硬件的操作。下面是一个简单的ARM架构下的中断处理程序示例,用于展示如何编写基本的RTOS功能模块: ```assembly .global _start .text _start: /* 设置堆栈指针 */ ldr sp, =stack_top init_os: /* 初始化系统时钟和其他外设 */ bl init_peripherals main_loop: b main_loop @ 主循环等待事件发生 /* 中断服务子程序模板 */ .section .text.isr_vector,"ax",%progbits isr_vector: ldr pc, [pc, #0x0] @ 复位向量 ldr pc, [pc, #0x4] @ NMI 向量 ... interrupt_handler: push {lr} @ 保存链接寄存器 /* 这里可以调用调度函数来切换任务上下文 */ bl scheduler @ 假定有一个名为scheduler的任务调度函数 pop {lr} bx lr @ 返回到被中断的地方 ``` 这段代码展示了RTOS中最基础的部分——初始化以及异常响应机制[^1]。 #### 教程推荐 为了更好地理解并掌握RTOS的工作原理及其汇编级实现方法,建议参考一些高质量的学习资料。例如,在线文档《超棒的嵌入式学习资源汇总》提供了丰富的关于不同平台上的单片机编程指南,包括但不限于MSP430、TM4C123系列MCU等的具体实践案例[^2];另外,《嵌入式系统综述》一文中也提到随着设备复杂度增加,应用需求促使开发者采用更高级别的操作系统支持以缩短开发周期,这同样适用于RTOS的设计理念探讨[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值