Intel x86_64 程序集比较带符号的双精度浮点数

Intel x86_64 assembly compare signed double precision floats

根据主题我遇到了问题。

在 xmm0 寄存器中我有一个值,例如-512.000000
在 xmm4 中:0.000000.

我尝试将第一个值与零进行比较,但我无法真正做到这一点。

comisd xmm0, xmm4

COMISD 指令以一种奇怪的方式设置标志,只有 jnz 之后才能在我的代码中正常工作。

如何进行比较?

COMISD 的一个常见问题是它设置标志的方式与普通比较略有不同。因此,COMISD 将设置如下:

大于:ZF:0、PF:0、CF:0

等于:ZF:1、PF:0、CF:0

小于 : ZF:0, PF:0, CF:1

因此,要衡量XMM0是否小于XMM4,需要做一个JC。

相信这会有所帮助。

这里有 Intel's IA-32 manual。 第 689 页是 COMISD 描述,它指出:

RESULT ← OrderedCompare(DEST[63:0] ≠ SRC[63:0]) {
(* Set EFLAGS *) CASE (RESULT) OF
    UNORDERED:    ZF,PF,CF ← 111;
    GREATER_THAN: ZF,PF,CF ← 000;
    LESS_THAN:    ZF,PF,CF ← 001;
    EQUAL:        ZF,PF,CF ← 100;
ESAC;
OF, AF, SF ← 0; }

178页也描述了哪个跳转指令是基于EFLAGS寄存器的哪个标志(EFLAGS在78页有描述)。

JC(如果进位则跳转)仅检查是否设置了 CF 标志 - 如果是,它可以是 less then 关系或 unordered

编辑: - 删除了错误的答案,以免误导任何人留下手册链接。

英特尔的手册记录了如何 COMISD 设置标志。

首先,使用 jp 检查无序(如果您希望您的代码对 NaN 输入正常工作)。

然后您可以使用任何 ja / jae / jb / jbe(高于/低于)条件或它们的否定条件(jna , 等),或 je / jne (等于/不等于)。这些与无符号整数比较的条件相同。显然 cmovcc 和 setcc 也可以工作。

这些条件有类似 jc 的同义词(如果 CF==1 则跳转),但 above/below 具有正确的语义,因此可以减少必要的注释量,使您的代码更人性化-可读。

您可以跳过 ja 等条件之前的 jp,因为 CF=0 意味着 PF=0。 (即,如果操作数是无序的,a 条件将为假)。

一些其他条件,如b(下面:CF=1)或be(CF=1 或 ZF=1),对于无序操作数为真,因此您需要分支在 jp 之前或之后 jb / jbe 如果您需要排除 NaN 输入。

如果我的逻辑正确,您可以反转比较操作数以允许使用 ja 而不是 jbe(例如)并将无序大小写与其他 "way" 分组。


历史意义/为什么这样设计:

请注意,comisd 的标志设置与您从 x87 fcom / fnstsw ax / sahf. See also this x87 tutorial/guide for an example of using that sequence. But only for historical interest! fcomi, which also sets the flags the same way, has been around for over 20 years (P6), and is faster. (See the 标记 wiki 获得的内容相匹配以获得更多链接)。

x87 仅对 80 位扩展精度有用,因为假设 SSE2 可用通常是安全的,即使在 32 位模式下也是如此。

另请参阅 以更详细地了解 x87 为什么使用这些标志,fcomi 和 SSE 保持与这些标志的兼容性。