You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM64汇编中limit变量为何被意外重置为0?

64位ARM汇编素数判断中变量被意外覆盖的问题分析与修复

问题根源

核心问题是数据类型宽度不匹配导致的内存越界覆盖:

  • 你在.data段用.word定义了testvalue、factor、limit,这是32位(4字节)的存储单元,且在内存中连续排列:testvalue → factor → limit。
  • 但代码中使用了64位寄存器(X0、X1等)的STR指令,这类指令会一次性写入8字节数据。

当执行第47行STR X1, [X0]时,X1的值是2(64位表示为0x0000000000000002),写入factor的4字节地址后,会额外覆盖后面4字节的内存——而这部分正好是limit的存储位置,limit被写入64位值的高4字节(全0),因此最终变为0。

从GDB调试时序看,第47行执行后GDB可能未立即刷新内存读取,直到步进至第49行时才显示出limit被覆盖后的0值。

解决方案

有两种可行的修复方式:

方式一:改用64位数据类型定义变量

将.data段中的.word替换为.dword(64位双字),让每个变量占用8字节,确保64位STR指令写入时不会越界覆盖相邻变量:

.data
testvalue: 
    .dword 0             // 64位存储单元
factor: 
    .dword 0         // 64位存储单元
limit: 
    .dword 0         // 64位存储单元

注意同步修改scanf和printf的格式符,将%d改为%ld以适配64位整数。

方式二:使用32位寄存器与指令

如果坚持使用32位.word变量,需改用32位寄存器(W0、W1等)和对应32位存储指令STR Wx, [Xy],确保只写入4字节:

  1. 第43行修改为:STR W0, [X1](写入limit时只用32位寄存器的内容)
  2. 第47行修改为:STR W1, [X0](写入factor时只用32位寄存器的内容)
  3. 所有读取变量的操作,也改用LDR Wx, [Xy]读取32位值,例如第34行LDR W0, [X0]、第40行LDR W0, [X0]等。

额外优化建议

  • 素数判断无需循环到testvalue-1,只需循环到sqrt(testvalue)即可大幅减少循环次数。
  • 可先判断输入是否为偶数,再从3开始以步进2的方式循环,进一步提升效率。

内容的提问来源于stack exchange,提问作者Andrew H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 13:00:54