ARM汇编STR指令写内存时超8位数值存储错误问题排查
问题原因
你出现这个问题的核心原因是ARM访存指令的位宽使用错误,且地址自增步长和指令位宽不匹配:
- ARM架构中,无后缀的
LDR/STR是32位字访存指令,执行时会连续读写目标地址起始的4个字节内存,而非1个字节。 - 你代码中设置的地址后自增偏移为
#1,和32位字访存要求的4字节步长完全不匹配。 - 你观测到的121正好是377(十六进制为
0x00000179)的最低8位值(0x79):Keil仿真默认使用小端存储模式,执行STR写入32位值时,会把最低字节存在目标地址、次低字节存在目标地址+1位置,剩下两个高位字节存在后续地址。你在内存面板按字节查看时,首先看到的目标地址位置的121就是被截断的低8位,高位的1被写到了下一个地址,之前数值小于256时,高位全为0,低8位正好等于完整数值,所以没有暴露出问题。
另外你的加载指令也存在同样的问题:用LDR做32位加载却每次地址只加1,本质是做非对齐字读取,只是因为之前读取的数值小于256,周边内存字节为0,才没出现计算错误。
解决方法
根据你的实际存储需求二选一即可:
- 如果你需要逐字节处理、存储8位数据(值域0-255):将所有访存指令替换为带字节操作后缀的
LDRB/STRB,保持步长1不变。注意377超出8位值域,用这种方式存储会被截断为低8位121,如果需要保留完整计算结果请选第二种方案。
修正后的代码段:LDRB R6, [R3],#1 ; 加载1字节到R6,高位自动清零 LDRB R7, [R4],#1 ; 加载1字节到R7,高位自动清零 ADD R5, R6, R7 ; 计算两数之和 STRB R5, [R12],#1; 存储R5低8位到内存,地址自增1 - 如果你需要存储完整的32位计算结果(支持大于255的值):保留
LDR/STR字访存指令,将地址自增步长从1改为4,同时保证R3、R4、R12的初始地址是4字节对齐(地址值可被4整除),避免触发对齐异常。
修正后的代码段:LDR R6, [R3],#4 ; 加载32位字到R6,地址自增4 LDR R7, [R4],#4 ; 加载32位字到R7,地址自增4 ADD R5, R6, R7 ; 计算两数之和 STR R5, [R12],#4; 存储R5完整32位值到内存,地址自增4
内容的提问来源于stack exchange,提问作者CingirakliDumbelek
相关产品推荐
相关产品推荐

