news 2026/5/23 5:20:40

ARM 汇编指令:LDM

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ARM 汇编指令:LDM

ARM 汇编指令:LDM

本文来自于我关于 ARM 汇编指令系列文章。欢迎阅读、点评与交流~
1、汇编指令在不同架构中的联系与区别
2、ARM 汇编指令:MOV
3、ARM 汇编指令:LDR
4、ARM 汇编指令:STR
5、ARM 汇编指令:MRS 和 MSR
6、ARM 汇编指令:ORRS
7、ARM 汇编指令:BEQ
8、ARM 汇编指令:TST
9、ARM 汇编指令:B
10、ARM 汇编指令:BX
11、ARM 汇编指令:ERET
12、ARM 汇编指令:STP\LDP
13、ARM 汇编指令:UBFX
14、ARM 汇编指令:STM
15、ARM 汇编指令:LDM

1. 核心定义

LDMLoad Multiple的缩写,意为“加载多个寄存器”。它是 ARM 汇编中用于从连续的内存地址中一次性加载数据到多个寄存器的指令。

它通常与STM指令配对使用,后者用于将多个寄存器的值存储到连续的内存中。

2. 基本语法

LDM{addr_mode}{cond} Rn{!}, reglist{^}
  • LDM:指令本身。
  • {addr_mode}地址模式后缀。这是关键部分,决定了地址的增长方式和数据的加载顺序。常见的有:
    • IA: Increment After (默认,可省略)。每次加载后地址增加。
    • IB: Increment Before。每次加载前地址增加(仅用于 ARM 特权模式)。
    • DA: Decrement After。每次加载后地址减少。
    • DB: Decrement Before。每次加载前地址减少。
  • {cond}:可选的条件码,如EQ,NE,GT等。
  • Rn基址寄存器,其中保存着内存起始地址。
  • {!}:可选的回写后缀。如果加上!,则指令执行后,会将计算得到的最终地址写回 Rn 基址寄存器。这在堆栈操作和数据块移动中非常有用。
  • reglist寄存器列表。用大括号{}括起来,包含要加载数据的寄存器。例如{R0, R4-R7, R10}。寄存器在列表中的顺序不重要加载总是按照寄存器编号从小到大的顺序进行,而地址的递增/递减方向由addr_mode决定。
  • {^}:可选的特权后缀。有两个含义:
    • 如果reglist包含 PC 寄存器^表示除了正常加载数据外,还会将 SPSR 的内容复制到 CPSR(用于从异常处理返回)。
    • 如果reglist不包含 PC 寄存器^表示加载的是用户模式下的寄存器,而不是当前特权模式的寄存器。

3. 工作原理(以最常见的 LDMIA 为例)

假设执行指令:LDMIA R0!, {R1, R3, R5}

  • 内存起始地址是 R0 中的值。
  • 虽然列表写的是{R1, R3, R5},但 ARM 硬件会按编号排序为R1, R3, R5
  • **IA(后增)**模式:
    1. [R0]处的 4 字节数据加载到R1
    2. [R0+4]处的 4 字节数据加载到R3
    3. [R0+8]处的 4 字节数据加载到R5
  • 因为使用了!,指令执行后,R0 = R0 + 12(3个寄存器 * 4字节)。

4. 与堆栈操作的关系

ARM 为堆栈操作(后进先出 LIFO)定义了更直观的别名。堆栈由**堆栈指针 SP(R13)**管理,可以向下增长(满递减)或向上增长(空递增)。

标准指令堆栈别名含义常见用途
LDMDBLDMFDFull Descending堆栈的弹出操作ARM 默认堆栈类型(向下增长,满栈)
LDMIALDMEAEmpty Ascending堆栈的弹出操作较少使用
STMDBSTMFDFull Descending堆栈的压入操作ARM 默认堆栈的压栈
STMIASTMEAEmpty Ascending堆栈的压入操作较少使用

记住这个口诀:PUSH = STMFDPOP = LDMFD

5. 经典用例

a) 块数据复制

; 将 R1 指向的源地址处的 4 个字,复制到 R2 指向的目标地址 LDMIA R1!, {R4-R7} ; 从源地址加载4个寄存器 STMIA R2!, {R4-R7} ; 存储到目标地址

b) 子程序进入/退出(保护与恢复寄存器)

; 进入子程序时,将工作寄存器压栈保护 STMFD SP!, {R4-R12, LR} ; 压栈,LR (R14) 是返回地址 ; ... 子程序主体 ... ; 退出子程序时,从堆栈恢复寄存器并返回 LDMFD SP!, {R4-R12, PC} ; 弹出,直接将返回地址加载到 PC (R15),实现跳转 ; 等同于 POP {R4-R12, PC}

c) 异常返回

; 从 IRQ 异常处理程序返回 SUBS PC, LR, #4 ; 简单方法 ; 或使用 LDM 从堆栈恢复所有上下文(包括 PC 和 CPSR) LDMFD SP!, {R0-R12, LR} ; 恢复通用寄存器和链接寄存器 RFEFD SP! ; 使用 RFE 指令返回(现代方式) ; 或者使用带 ^ 的 LDM(传统方式) ; LDMFD SP!, {R0-R12, PC}^ ; ^ 表示同时将 SPSR 复制到 CPSR

6. 重要注意事项

  1. 加载顺序固定:无论reglist如何书写,总是R0(如果存在)从最低地址加载,R1从下一个地址加载,以此类推。
  2. 基址寄存器对齐:地址通常是字对齐的(4字节边界)。
  3. PC 的特殊性:如果reglist包含 PC(R15),它总是最后被加载。加载到 PC 的值将导致程序跳转。
  4. 效率:一条LDM指令可以加载多个寄存器,这比用多条LDR指令更高效,因为它减少了指令取指和解码的开销。

总结

LDM是 ARM 架构中一个强大且高效的批量数据加载指令,尤其在与STM配对用于堆栈操作内存块复制时,是 ARM 汇编编程的基石之一。理解其地址模式(特别是IA/DB)和与堆栈别名(FD/EA)的关系,是掌握它的关键。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/22 15:25:27

Conda环境导出与迁移:Miniconda-Python3.10保障项目可复现

Conda环境导出与迁移:Miniconda-Python3.10保障项目可复现 在人工智能和数据科学项目中,一个常见的困扰是:“代码在我机器上能跑,为什么换台设备就报错?”这种“环境不一致”问题不仅浪费开发时间,更可能让…

作者头像 李华
网站建设 2026/5/10 21:52:53

Anaconda配置PyTorch环境慢?Miniconda-Python3.10提速秘诀

Miniconda-Python3.10:轻量构建PyTorch环境的高效实践 在深度学习项目中,每次换机器或复现实验时,最让人焦躁的不是写代码,而是卡在环境配置上——尤其是用Anaconda安装PyTorch时,动辄几分钟甚至十几分钟的依赖解析和…

作者头像 李华
网站建设 2026/5/23 18:08:04

Conda环境初始化错误终极解决:Miniconda-Python3.10预激活shell

Conda环境初始化错误终极解决:Miniconda-Python3.10预激活shell 在人工智能和数据科学项目中,你是否曾遇到过这样的场景:刚启动一个远程Jupyter实例,满怀期待地打开Terminal,输入conda activate myenv,却收…

作者头像 李华
网站建设 2026/5/23 18:08:26

无需完整Anaconda:Miniconda-Python3.10满足所有PyTorch开发需求

无需完整Anaconda:Miniconda-Python3.10满足所有PyTorch开发需求 在AI模型训练日益频繁的今天,你是否也遇到过这样的场景?刚拿到一台新的GPU服务器,满心欢喜准备复现一篇论文,结果一运行代码就报错——“torch.cuda.is…

作者头像 李华
网站建设 2026/5/14 21:11:52

新规解读|《网络安全法》2025年修正版深度解读:关键变化与技术影响

2025年10月28日,第十四届全国人大常委会第十八次会议通过《关于修改〈中华人民共和国网络安全法〉的决定》,对2017年施行的《网络安全法》作出系统性修订。这是该法实施八年以来的首次重大修正,标志着我国网络空间治理体系进入“强监管、重安…

作者头像 李华
网站建设 2026/5/10 14:32:26

Java方法返回多个值

<dependency><groupId>org.javatuples</groupId><artifactId>javatuples</artifactId><version>1.2</version> </dependency>Javatuples 支持最大为 "10" 的元组大小&#xff0c;对于每种大小&#xff0c;它都提供了…

作者头像 李华