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

x87能否对无符号Quadword整数执行精确除法?代码余数异常求助

x87能否对无符号64位整数执行精确除法?

无符号64位整数精确除法的可行性

x87 FPU虽以有符号数为设计核心,仅明确支持有符号16/32/64位整数类型,但完全可以实现无符号64位整数的精确除法:

  1. 精度覆盖:x87采用的80位扩展精度浮点数拥有64位尾数(加隐含有效位),可精确表示所有64位整数,包括无符号范围0~2^64-1的全部数值。
  2. 运算精确性:根据英特尔手册描述,只要运算的真实结果是整数且在范围内,FPU对整数的运算会返回精确结果。无符号64位除法的商和余数均为整数,符合这一条件。
  3. 注意事项:
    • 加载无符号64位整数时,需用fild当作有符号数加载。当无符号数大于2^63-1时,会被识别为有符号负数,但FPU对该值的浮点表示仍是精确的。
    • 计算余数时,由于FPU余数符号与除数一致(有符号规则),需将余数调整为非负值,以符合无符号除法的要求。

你的有符号64位除法代码余数为0的原因

你的代码核心错误是栈布局与数据加载不匹配,导致FPU加载的并非输入的被除数和除数,而是寄存器垃圾值,最终出现余数始终为0的异常:

错误点分析

输入的被除数是edx:eax(64位),除数是ecx:ebx(64位),但你执行push edi ecx ebx edx eax后,栈的布局(从esp开始)为:

  • [esp]:edi(32位)
  • [esp+4]:ecx(32位)
  • [esp+8]:ebx(32位)
  • [esp+12]:edx(32位)
  • [esp+16]:eax(32位)

后续fild qword [edi](即fild qword [esp])加载的是ecx:edi组成的64位值,而非输入的被除数edx:eax;fild qword [edi+8]加载的是edx:ebx组成的64位值,也不是输入的除数ecx:ebx。错误的输入数据导致计算逻辑完全偏离预期,进而出现余数始终为0的情况。

修正后的栈操作示例

正确的做法是按顺序压入被除数和除数的64位数据:

FiDiv:  push    eax edx ebx ecx  ; 先压被除数低32位eax,再压高32位edx;然后压除数低32位ebx,高32位ecx
        mov     edi, esp
        fninit
        fild    qword [edi]     ; 加载被除数(edx:eax,小端序下低地址是eax,高地址是edx)
        fild    qword [edi+8]   ; 加载除数(ecx:ebx)
        ; 后续逻辑保持不变

其他潜在注意点

  • fninit会将FPU舍入模式重置为“就近舍入”,你后续修改为“向零截断”的操作符合idiv的行为,是正确的。
  • 你通过fnstsw检测8000000000000000h / -1的溢出情况并设置CF的逻辑是合理的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:40:09