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

64位无符号数乘法结果错误:原因排查与修正咨询

64位无符号数相乘转128位结果的HLA代码问题

尝试用HLA实现两个64位无符号数相乘并将结果存入128位变量,参考相关方法编写代码后,测试小数值(如$84B8_8BF3_1E4E_3B0C)结果正确,但测试最大64位无符号数$FFFFFFFFFFFFFFFF时,输出结果与预期的FFFFFFFFFFFFFFFE0000000000000001不符,第13字节出错。将代码最后一行的adc(0,edx);改为adc(1,edx);后问题解决,现咨询以下问题:

  • 这个1的来源是什么?
  • 代码中的错误在哪里?
  • 如何正确修改程序?

原始代码:

program exercise;
static  

      qw1:qword:=  956_3547_6850_2300_5452;//$84B8_8BF3_1E4E_3B0C 
      qw2:qword:=  956_3547_6850_2300_5452;//$84B8_8BF3_1E4E_3B0C
  //qw1:qword:=  18_446_744_073_709_551_615;//$FFFF_FFFF_FFFF_FFFF
  //qw2:qword:=  18_446_744_073_709_551_615;//$FFFF_FFFF_FFFF_FFFF

    prd:lword :=0;
  
#include("Stdlib.hhf");

begin exercise;
mov((type dword qw1[0]),eax);
mul((type dword qw2[0]),eax);
mov(eax,(type dword prd[0]));
mov(edx,ecx);

mov((type dword qw1[4]),eax);
mul((type dword qw2[0]),eax);
add(ecx,eax);
mov(eax,ebx);
adc(0,edx);
mov(edx,ecx);

mov((type dword qw1[0]),eax);
mul((type dword qw2[4]),eax);
add(ebx,eax);
mov(eax,(type dword prd[4]));
adc(ecx,edx);
mov(edx,ecx);

mov((type dword qw1[4]),eax);
mul((type dword qw2[4]),eax);
add(ecx,eax);
mov(eax,(type dword prd[8]));
adc(0,edx);
mov(edx,(type dword prd[12]));
stdout.put(prd, "     ",(type uns128 prd));

end exercise;

解答

1. 这个1的来源是什么?

你改成adc(1,edx)能解决问题是巧合,这个1并非正确逻辑里的固定值。实际正确逻辑中,需要加到edx的是第四步add(ecx,eax)执行后产生的进位标志CF。由于前面步骤的错误,导致ecx值异常,add(ecx,eax)实际产生了CF=1,手动加1刚好抵消了前面的错误,但这不是正确的解决方式。

2. 代码中的错误在哪里?

核心错误出在第三步的进位处理逻辑:

adc(ecx,edx);
mov(edx,ecx);

这部分完全颠倒了操作对象。第三步中,add(ebx,eax)会产生进位CF,我们需要把a0*b1的高32位(存在edx)和进位CF一起加到之前累积的进位值ecx中,而不是把ecx加到edx里。这一错误导致ecx存储的累积进位值错误,最终在第四步计算时,add(ecx,eax)的结果异常,进而影响最高32位的输出结果。

另外,第四步的adc(0,edx)本身逻辑是正确的(将add产生的CF加到edx),但因为前面的错误,才需要手动改1来“修复”。

3. 如何正确修改程序?

修正第三步的进位处理逻辑,将错误的:

adc(ecx,edx);
mov(edx,ecx);

改为:

adc(edx, ecx);

(HLA中adc(source, dest)表示dest = dest + source + CF,这行代码直接把edx和CF加到ecx中,无需再执行mov(edx,ecx))

完整修正后的代码:

program exercise;
static  

      qw1:qword:=  18_446_744_073_709_551_615;//$FFFF_FFFF_FFFF_FFFF
      qw2:qword:=  18_446_744_073_709_551_615;//$FFFF_FFFF_FFFF_FFFF
  //qw1:qword:=  956_3547_6850_2300_5452;//$84B8_8BF3_1E4E_3B0C 
  //qw2:qword:=  956_3547_6850_2300_5452;//$84B8_8BF3_1E4E_3B0C

    prd:lword :=0;
  
#include("Stdlib.hhf");

begin exercise;
mov((type dword qw1[0]),eax);
mul((type dword qw2[0]),eax);
mov(eax,(type dword prd[0]));
mov(edx,ecx);

mov((type dword qw1[4]),eax);
mul((type dword qw2[0]),eax);
add(ecx,eax);
mov(eax,ebx);
adc(0,edx);
mov(edx,ecx);

mov((type dword qw1[0]),eax);
mul((type dword qw2[4]),eax);
add(ebx,eax);
mov(eax,(type dword prd[4]));
adc(edx, ecx); // 修正此处的进位处理逻辑

mov((type dword qw1[4]),eax);
mul((type dword qw2[4]),eax);
add(ecx,eax);
mov(eax,(type dword prd[8]));
adc(0,edx); // 保留正确的逻辑
mov(edx,(type dword prd[12]));
stdout.put(prd, "     ",(type uns128 prd));

end exercise;

修改后,无论是小数值还是最大64位无符号数,计算结果都会与预期一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:17:05