ARM LDM/STM IA模式示例中,为何执行STM后R6指向内存存储10、11、12
ARM LDM/STM 指令调试疑问解答
核心规则先明确
- 不带后缀的
ldm/stm默认采用**IA(事后增量)**寻址模式:访问内存时从基址寄存器保存的地址开始,每访问一个4字节单元,临时将偏移加4,完成所有寄存器的访问后,再根据模式计算最终地址偏移。 - 指令如果没有
!写回后缀,整个指令执行过程中,基址寄存器的数值不会被修改。 - 指令数据流方向完全相反:
ldm是将连续内存值加载到目标寄存器列表,方向为内存→寄存器;stm是将目标寄存器列表的值写入连续内存,方向为寄存器→内存。
为什么第30行看到的内存值不是LDM加载的r3/r4/r5值?
按调试时序完整拆解流程:
- 执行完
ldr r6, =mem后,r6被赋值为mem段的起始地址0x1050c,此时该地址起始的3个连续内存单元存储值为0x1、0x2、0x3,对应调试流程中16-17行的输出结果。 - 执行
ldm r6, {r3, r4, r5}(IA模式、无写回):- 从r6保存的
0x1050c开始,依次读取3个连续4字节内存值,按寄存器列表顺序赋值:r3=0x1、r4=0x2、r5=0x3,和调试流程23-26行的寄存器输出完全匹配。 - 因为无写回后缀,r6的值全程保持
0x1050c,没有发生变化。
- 从r6保存的
- 执行后续的
stm r6, {r0, r1, r2}:- 此时r0已经被设为10(0xa)、r1=11(0xb)、r2=12(0xc)。
- 这条指令会从r6保存的
0x1050c开始,依次把r0、r1、r2的值写入连续内存单元,直接把之前存储的0x1、0x2、0x3覆盖为0xa、0xb、0xc。
此时再查询r6指向的内存,看到的自然是被STM覆盖后的10、11、12的对应值。LDM仅完成内存到寄存器的读取,从来没有把寄存器值反向写回内存的操作,自然不会在内存里看到r3/r4/r5的数值。
STM指令是把R6寄存器中存储的数值写入目标内存吗?
这个理解完全错位:
- STM的操作对象是寄存器列表内的通用寄存器值,r6在这条指令里的角色是内存地址的提供者:r6中存储的数值是目标内存的起始地址,本身不会被当作待写入的存储内容。
- 本次调试中的实际操作链路是:
- 从r6读取保存的地址
0x1050c作为写入起点 - 依次将r0(0xa)、r1(0xb)、r2(0xc)的值写入该起点开始的连续3个内存单元
- 因为无写回后缀,r6自身的数值全程保持
0x1050c不变。
- 从r6读取保存的地址
内容的提问来源于stack exchange,提问作者Ben K
相关产品推荐
相关产品推荐

