ARM 架构中,R14链接寄存器(LR)是什么?

ARM 架构中,R14链接寄存器(LR)是什么?

本文来自于我关于 Arm Cortex-M 编程模型的系列文章。欢迎阅读、点评与交流~
1、Arm Cortex-M 处理器的编程模型
2、ARM 架构中,R13栈指针(SP)是什么?
3、ARM 架构中,R14链接寄存器(LR)是什么?

核心定义

R14,即链接寄存器(全称:Link Register) ,是 ARM 处理器 16 个通用寄存器(R0-R15)中的一个。它的主要职责是 存储子程序或函数调用的返回地址

当程序使用 BL(Branch with Link)或 BLX 指令调用一个子程序(函数)时,处理器在跳转到目标地址执行之前,会自动将下一条指令的地址(即返回地址)保存到 LR(R14)中。子程序执行完毕后,通过将 LR 的值复制到程序计数器 PC(R15),即可返回到主调程序继续执行。


主要功能与用途

  1. 保存返回地址(核心功能)

    • 这是 LR 最基本、最重要的作用。

    • 示例:

      assembly 复制代码
      main:
          ...
          BL subroutine    ; 调用子程序。执行此指令时,下一行 MOV 指令的地址会被自动存入 LR
          MOV r0, #5       ; <-- 这是返回地址,被保存在 LR 中
          ...
      
      subroutine:
          ...              ; 子程序代码
          BX LR           ; 将 LR 的值载入 PC,从而返回到 main 的 MOV 指令处
  2. 异常处理时的状态保存

    • 当发生异常(如中断、系统调用)时,处理器在进入异常模式前,会将当前模式的返回地址保存到异常模式下的 LR (例如 LR_irq, LR_svc)。
    • 这确保了异常处理程序完成后,能正确返回到被中断的程序点。
    • 注意: 此时的 LR 保存的值可能与正常函数返回地址略有不同(例如会进行自动偏移校正),这取决于具体的异常类型和 ARM 架构版本。
  3. 作为临时通用寄存器

    • 在函数内部,一旦返回地址被安全地保存到栈上 (通常在函数开头通过 PUSH {LR}STR LR, [sp, #-4]!),LR 就可以在后续代码中作为一个普通的临时寄存器(相当于 R14)使用,以增加寄存器资源的灵活性。

关键特性与注意事项

  • 调用嵌套与栈保存

    LR 是单副本寄存器。如果一个函数(A)内部又调用了另一个函数(B),那么在调用 B 之前,函数 A 的返回地址(保存在 LR 中)会被 B 的调用覆盖。

    • 解决方案: 在非叶子函数(即那些还会调用其他函数的函数)的开头,必须先将 LR 的值压入内存栈进行保存,在函数结束前再从栈中恢复。

    • 标准序言/尾声:

      assembly 复制代码
      my_function:
          PUSH {LR}          ; 将返回地址保存到栈
          ...                ; 函数体,可以安全地调用其他函数
          BL another_func
          ...
          POP {PC}           ; 从栈中弹出之前保存的地址,直接载入 PC 以实现返回
                             ; 这是一种常见的优化技巧
  • 与 PC(R15)的关系

    LR 和 PC 紧密协作。BL 指令完成 LR = PC + offset 的写入,而 BX LRMOV PC, LR 则完成从子程序返回的操作。

  • 在 ARM 操作模式和 Banked Registers

    ARM 有多种处理器模式(User, FIQ, IRQ, SVC, Abort 等)。不同模式拥有自己独立的 R14 物理副本(称为"分组寄存器")。

    • 例如,当在 User 模式下执行 BL 指令时,返回地址保存在 User 模式的 LR 中。
    • 当发生 IRQ 中断时,处理器自动切换到 IRQ 模式,并将返回地址保存到 LR_irq(IRQ 模式专用的 R14),而 User 模式的 LR 值保持不变,不受影响。
    • 这为不同模式提供了独立的调用返回链,是硬件上下文切换的关键部分。
  • 架构差异

    • ARMv7-A/R 和更早的架构中,LR 就是 R14。
    • 64位的 ARMv8-A 架构中,寄存器文件扩展为 31 个 64 位通用寄存器(X0-X30)。X30 寄存器承担了链接寄存器的角色,其功能和原理与 ARM32 下的 R14 完全相同。

总结

特性 描述
名称 R14 / 链接寄存器 / Link Register / LR
核心目的 存储函数调用(BL指令)后的返回地址
关键操作 BL/BLX 指令自动写入;通过 BX LRMOV PC, LR 返回
嵌套调用 必须在调用其他函数前,将其值压入栈保存,否则会被覆盖
异常处理 各异常模式有自己的分组 LR,用于保存异常返回地址
临时使用 在保存好返回地址后,可临时作为通用寄存器使用

简单来说,LR 是函数调用的"书签",它告诉程序"你从哪儿来的,执行完了就该回哪儿去"。它是实现结构化编程和子程序调用的硬件基础。

相关推荐
森G3 小时前
七、04ledc-sdk--------makefile有变化
linux·c语言·arm开发·c++·ubuntu
VekiSon7 小时前
Linux内核驱动——杂项设备驱动与内核模块编译
linux·c语言·arm开发·嵌入式硬件
AI+程序员在路上7 小时前
Nand Flash与EMMC区别及ARM开发板中的应用对比
arm开发
17(无规则自律)13 小时前
深入浅出 Linux 内核模块,写一个内核版的 Hello World
linux·arm开发·嵌入式硬件
梁洪飞1 天前
内核的schedule和SMP多核处理器启动协议
linux·arm开发·嵌入式硬件·arm
代码游侠2 天前
学习笔记——Linux字符设备驱动
linux·运维·arm开发·嵌入式硬件·学习·架构
syseptember2 天前
Linux网络基础
linux·网络·arm开发
代码游侠2 天前
学习笔记——Linux字符设备驱动开发
linux·arm开发·驱动开发·单片机·嵌入式硬件·学习·算法
程序猿阿伟2 天前
《Apple Silicon与Windows on ARM:引擎原生构建与模拟层底层运作深度解析》
arm开发·windows
wkm9562 天前
在arm64 ubuntu系统安装Qt后编译时找不到Qt3DExtras头文件
开发语言·arm开发·qt