一图看懂MCU通用寄存器:SP、LR、PC不再是天书!

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习

🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发

❄️作者主页:一个平凡而乐于分享的小比特的个人主页

✨收录专栏:硬件知识,本专栏为记录项目中用到的知识点,以及一些硬件常识总结

欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

🔥 一图看懂MCU通用寄存器:SP、LR、PC不再是天书!

你是不是也见过 SPLRPC 这些缩写?

看着像密码,其实是MCU的"三大交通指挥员"🚦

这篇用最通俗的比喻 + 表格 + 场景示例,一次搞懂它们!


🧠 先记住一句话(核心理解)

PC 指路SP 管堆栈LR 记回家的路


📦 什么是"通用寄存器"?

MCU内部有一组极高速的小存储单元 ,叫寄存器。

其中大部分可以做通用计算 (比如 R0、R1、R2...),但有几个有特殊任务

缩写 全称 通俗角色
PC Program Counter 📍 导航员 -- 指到哪,执行到哪
SP Stack Pointer 📚 图书管理员 -- 管理堆栈的书(数据)
LR Link Register 🏠 记门牌号 -- 记住函数调用后要回哪里

这三者 不是"通用运算寄存器" (如 R0 可随意算数),

而是有专用职责的寄存器,但常与"通用寄存器组"一起学。


🧭 1. PC(程序计数器)------ 代码的"导航员"

📍 作用:

下一条要执行的指令的地址

🚗 场景类比:

你去图书馆按索书号找书:

  • 每看完一页 → 页码 +1
  • 如果跳页(goto/if/函数调用)→ 直接改页码

PC 就是那个"当前页码"

⚙️ 示例:

assembly 复制代码
MOV R0, #5    ; 假设地址 0x100
ADD R1, R0    ; 地址 0x104
BL  func      ; 地址 0x108 → PC 会变

执行过程:

  1. 上电 → PC = 0x100
  2. 执行完 0x100 → PC = 0x104
  3. 执行完 0x104 → PC = 0x108
  4. 遇到 BL → PC 跳到 func 地址

🧺 2. SP(堆栈指针)------ 数据的"临时仓库管理员"

📦 作用:

指向当前堆栈的顶部 (或底部,取决于体系结构)。

用于:函数调用、保存临时数据、中断现场。

🧺 场景类比:

自助餐厅的叠盘子机

  • 压入(Push)→ 盘子往上放
  • 弹出(Pop) → 从顶上取

SP 永远指着最上面那个盘子

🔁 典型变化:

操作 SP 变化 含义
Push R0 SP - 4 存一个数据
Pop R0 SP + 4 取一个数据
函数调用 SP 调整 保存返回地址 & 局部变量

⚠️ 不同MCU堆栈增长方向不同(ARM 常用满递减栈,看图👇)

markdown 复制代码
高地址 ↑
        +--------+
        |  ...   |
SP →    | 数据C  |  ← 栈顶
        | 数据B  |
        | 数据A  |
低地址 +--------+

🏠 3. LR(链接寄存器)------ 记住"回家路"

🏡 作用:

当调用子函数时,保存返回地址(PC 的值)。

📞 场景类比:

你出门去朋友家(跳去函数)

→ 出门前在手机上记下自己家的门牌 (存入 LR)

→ 在朋友家吃完饭后,看手机 → 回家(LR → PC)

🔁 示例流程:

assembly 复制代码
main:
    BL  delay     ; ① PC 跳去 delay
                  ; ② 同时 PC+4 存入 LR

delay:
    ...           ; 执行延时
    BX  LR        ; ③ 把 LR 写回 PC → 回 main

如果没有 LR 会怎样? → 永远回不来 😱


🆚 对比总表(精华版)

寄存器 全称 存什么 谁改它(典型) 不设置会怎样
PC Program Counter 指令地址 分支 / 调用 / 中断 程序不动或跑飞
SP Stack Pointer 栈顶地址 Push / Pop / 函数进入 数据覆盖 / 崩溃
LR Link Register 返回地址 BL / 函数调用 回不到调用点

🧩 综合场景:一次函数调用 + 中断

你写了一个 MCU 程序:

c 复制代码
void delay() { ... }   // 延时函数
void main() {
    delay();           // 调用
    // 此处发生中断 ⚡
}

寄存器表演过程:

步骤 PC 在干嘛 SP 在干嘛 LR 在干嘛
① main 执行 指向下一条 稳定 无特殊
② 调用 delay 跳到 delay 调整(存返回地址) 保存 main 中下一条地址
③ delay 执行 在 delay 里 可能存局部变量 还是旧 LR
④ 中断发生(嵌套) 跳到 ISR 再次调整 LR 被改存中断返回地址
⑤ 中断返回 恢复 恢复 恢复
⑥ delay 返回 从 LR 恢复 恢复 恢复 main 地址

✅ 这就是 MCU 能嵌套调用、中断不崩的秘密


🧪 小测验(检验真懂了吗)

  1. 如果 PC 被改成 0,会发生什么?
  2. 忘记设置 SP,直接用 Push 指令会怎样?
  3. 一个函数里没有 BX LR,函数结束后 MCU 会去哪?

💡 答案:

1 -- 复位 / 跑飞

2 -- 堆栈溢出 / 数据错乱

3 -- 继续往下执行(大概率崩溃)


📌 一句话回顾

PC 指路SP 管堆栈LR 记回家的路

它们是 MCU 的"三大交通官",不是普通计算寄存器,但比普通寄存器还重要!