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

FCOMIP指令相关NASM双精度数比较代码结果不一致求助

我一眼就看到问题出在跳转指令的选择上——你用了整数指令jge来处理浮点数比较的结果,但fcomip对EFLAGS的设置方式和整数指令预期的完全不匹配,导致跳转逻辑几乎总是出错。

具体来说,fcomip只会修改EFLAGS的CF、PF、ZF位,同时把SF和OF清零。而jge(有符号整数的“大于等于”跳转)的条件是(SF == OF) || ZF。由于SF和OF都是0,SF == OF永远为真,所以不管你的两个浮点数实际大小如何,jge几乎都会跳转到minmax1_next分支,也就是总是选择a作为最小值——只有当a本身就是较小值的时候结果才正确,一旦b更小,结果就错了,这正好符合你说的“有时正确有时不正确”的现象。

给你几个修复方案,按推荐程度排序:

方案1:用SSE指令直接取最小值(最简洁可靠)

如果你的CPU支持SSE2(现在几乎所有x86 CPU都支持),直接用专门的minsd指令就行,完全不需要折腾x87栈和标志位:

movsd xmm0, qword [a]   ; 把a加载到xmm0
minsd xmm0, qword [b]   ; xmm0 = min(a, b)
movsd qword [minval], xmm0 ; 把结果存到minval

方案2:修正跳转指令,用jae代替jge

如果你坚持用x87的写法,把jge换成jae就可以。jae是无符号的“大于等于”跳转,它的条件是CF == 0,正好匹配fcomip的结果:当b >= a时,CF会被设为0,此时jae跳转去选a;当b < a时,CF为1,不跳转,选b。修正后的代码:

fld qword[a]
fld qword[b]
fcomip                  ; 比较ST0(b)和ST1(a),弹出ST0
fstp qword [float_temp_var] ; 清空x87栈
jae minmax1_next        ; b >= a时跳转
movsd xmm0,[b]
movsd [minval],xmm0
jmp minmax1_out
minmax1_next:
movsd xmm0,[a]
movsd [minval],xmm0
minmax1_out:

方案3:用x87的条件移动指令(避免跳转)

另一种x87写法是用fcmovb条件移动指令,不需要跳转,代码更流畅:

fld qword [a]
fld qword [b]
fcomi st0, st1          ; 比较ST0(b)和ST1(a),不弹出栈
fcmovb st0, st1         ; 如果b < a,把ST1(a)复制到ST0,此时ST0是较小值
fstp qword [minval]     ; 把最小值存入minval,弹出栈顶
fstp qword [float_temp_var] ; 清空x87栈剩余内容

另外提醒一句:混合x87和SSE指令本身没问题,但如果能用SSE就尽量用,x87的栈操作很容易出错,像你这次的问题就是典型的标志位理解错误导致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:39:49