news 2026/2/6 9:13:27

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/2/5 9:54:04

Pyenv与Miniconda协同工作:实现Python版本与环境双重控制

Pyenv与Miniconda协同工作:实现Python版本与环境双重控制 在人工智能和数据科学项目日益复杂的今天,开发者常面临一个看似简单却极为棘手的问题:为什么我的代码在同事的机器上跑不通? 答案往往藏在那些看不见的细节里——Python…

作者头像 李华
网站建设 2026/2/5 19:22:18

CUDA安装不再难:Miniconda-Python3.10镜像内置最佳实践配置

CUDA安装不再难:Miniconda-Python3.10镜像内置最佳实践配置 在深度学习和高性能计算的日常开发中,最让人头疼的往往不是模型设计或算法优化,而是环境搭建本身。你是否经历过这样的场景:刚拿到一台新的GPU服务器,满心期…

作者头像 李华
网站建设 2026/2/5 20:52:34

GitHub Actions持续集成:Miniconda-Python3.10自动测试AI脚本

GitHub Actions持续集成:Miniconda-Python3.10自动测试AI脚本 在人工智能项目开发中,你是否经历过这样的场景?本地训练好的模型脚本推送到GitHub后,CI却报错“ModuleNotFoundError”;或者同事拉下代码运行失败&#xf…

作者头像 李华
网站建设 2026/2/3 15:43:59

Markdown撰写技术博客:记录Miniconda配置PyTorch全过程

Miniconda 配置 PyTorch 全流程实战:打造高效可复现的 AI 开发环境 在深度学习项目中,最让人头疼的往往不是模型调参,而是“我这边跑得好好的,你那边怎么报错?”——依赖冲突、版本不一致、环境缺失……这些问题几乎每…

作者头像 李华
网站建设 2026/2/5 7:01:10

中华人民共和国网络安全法

(2016年11月7日第十二届全国人民代表大会常务委员会第二十四次会议通过 根据2025年10月28日第十四届全国人民代表大会常务委员会第十八次会议《关于修改〈中华人民共和国网络安全法〉的决定》修正)目  录第一章 总  则第二章 网络安全支持与促进第…

作者头像 李华
网站建设 2026/2/4 6:03:58

项目分享|Open-AutoGLM:让AI真正“上手”你的手机

引言 在智能设备普及的今天,如何让手机更“懂”用户需求,实现自动化任务处理,成为提升效率的重要方向。Open-AutoGLM 作为一款基于 AutoGLM 构建的手机端智能助理框架,通过多模态技术与自动化操作的结合,让用户只需用…

作者头像 李华