ARM汇编迭代数组时为何给寄存器加#4而非#1推进地址?
ARM汇编数组遍历地址偏移问题
你分析的这段是ARM架构下实现整数数组累加求和的汇编代码,完整代码如下:
RES: .word 0 N: .word 5 NUM1: .word 3, -17, 27, -12, 322 LDR r1, N ADR r2, NUM1 MOV r0, #0 LOOP: LDR r3, [r2] ADD r0, r0, r3 ADD r2, r2, #4 SUB r1, r1, #1 CMP r1, #0 BGT LOOP STR r0, RES
ADD r2, r2, #4这行的作用是把指向数组当前元素的指针移动到下一个元素,不能替换成ADD r2, r2, #1的原因非常明确:
- ARM、x86等绝大多数通用CPU都采用字节编址规则:内存中每个独立地址对应1字节(8bit)的存储空间,地址数值加1,只会向后移动1个字节的位置,不会直接跳到下一个同类型数据。
- 代码中
.word伪指令定义的是32位(即4字节)长度的数据:不管是存结果的RES、存数组长度的N,还是NUM1数组里的每个整数,单个元素都要占用连续4个字节的内存空间。
举个实际排布的例子:如果NUM1标签对应的起始内存地址是0x2000,数组各元素的地址分布为:- 第一个元素3:占用
0x2000~0x2003共4个地址 - 第二个元素-17:占用
0x2004~0x2007共4个地址 - 后续每个元素的起始地址,都比上一个元素的起始地址高4
- 第一个元素3:占用
- 循环里的
LDR r3, [r2]指令,会从r2存储的地址开始,读取连续4字节的完整32位字数据存入r3寄存器。如果每次只给r2加1,下一次读取的起始地址仅向后偏移1字节,读到的是上一个元素残留的3字节和下一个元素首字节拼接出的错误值,根本不是目标数组元素。 - 只有少数教学用的简化虚拟CPU会采用字编址模式,地址加1就对应跳过一个字长的数据,这种场景下才会写偏移1的逻辑,但真实商用架构都不采用这种编址方式。
内容的提问来源于stack exchange,提问作者julien1h
相关产品推荐
相关产品推荐

