You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在RARS中正确实现无符号32位整数乘法?

正确实现RISC-V无符号64位整数乘法的方法

首先,咱们先梳理下你代码里的核心问题:数字处理的逻辑顺序反了,而且对mulhu的使用场景和64位值的乘法拆分理解有误。

问题分析

你当前的代码是先把新数字加到s3(低32位),再乘以10,这不符合“逐位构建整数”的逻辑——正确的逻辑应该是先把当前的64位值乘以10,再加上新的数字。另外,mulhu是用来获取无符号32×32乘法的高32位结果,但你只单独调用它却没有把结果合并到高32位寄存器s4里,这就导致高32位一直是0,看起来s3也没正确更新。

另外要记住:RISC-V中,mul指令的低32位结果对于有符号和无符号乘法是完全相同的,区别只在高32位(mulh对应有符号,mulhu对应无符号)。所以处理无符号64位值的乘法时,需要同时计算低32位的乘积和高32位的进位/乘积。

修正后的代码实现

下面是修正后的biggerthan0段逻辑,专门处理无符号64位值的×10 + 新数字操作:

biggerthan0:
addi t0, t0, 1       # 移动到下一个字符
sub t2, t2, t4       # 将ASCII字符转为数字(0-9)

# 第一步:将当前64位值(s4:s3)乘以10
mul s3, s3, s2       # 计算低32位×10,结果存在s3(无符号和有符号低32位结果一致)
mulhu t6, s3, s2     # 计算低32位×10的高32位部分
mul t7, s4, s2       # 计算高32位×10的低32位部分
add s4, s4, t6       # 把低32位乘法的高32位加到高32位寄存器
add s4, s4, t7       # 加上高32位乘法的低32位,得到完整的高32位结果

# 第二步:加上新的数字t2
add s3, s3, t2       # 先加到低32位
bltu s3, t2, carry   # 无符号加法溢出判断:若加前的s3 < t2,说明加完后溢出
j digit

carry:
addi s4, s4, 1       # 高32位加1处理进位
j digit

关键细节解释

  1. 64位值的乘法拆分:当你要把64位值(s4 << 32 | s3)乘以10时,需要拆分计算:
    • 低32位s3×10,低32位结果留在s3,高32位部分加到s4
    • 高32位s4×10,低32位结果加到s4(由于10数值较小,这部分的高32位不会产生溢出)
  2. 无符号加法的溢出判断:无符号数加法中,若a + b溢出,等价于a < (2^32 - b),所以用bltu s3, t2, carry来判断加完新数字后是否需要向高32位进位。
  3. mulhu的正确用法mulhu rd, rs1, rs2会计算rs1 × rs2的无符号高32位,必须将这个结果合并到高32位寄存器s4,才能完整更新64位值的高半部分。

额外优化建议

  • 你定义的s5 = 429496729(2^32-1)/10,这个值原本是用来判断乘法是否会溢出,但在修正后的逻辑里,我们通过拆分乘法和单独处理进位,已经不需要这个判断了,可以移除。
  • 记得在最终输出64位结果时,要同时打印s4(高32位)和s3(低32位),确保完整输出64位无符号数。

内容的提问来源于stack exchange,提问作者Sotaro Suzuki

火山引擎 最新活动