英特尔x86_64程序集比较签名的双精度浮点数

时间:2016-06-11 16:37:16

标签: assembly x86-64 intel precision sse

根据主题,我遇到了问题。

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

我尝试将第一个值与零进行比较,但我无法实现这一点。

comisd xmm0, xmm4

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

我该如何进行这种比较?

3 个答案:

答案 0 :(得分:6)

英特尔的手册文档COMISD如何设置标记。

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

然后,您可以使用任何ja / jae / jb / jbe(上/下)条件或其否定值(jna等),或je / jne(等于/不等于)。这些条件与无符号整数比较的条件相同。显然cmov和setcc也有效。

这些条件具有jc之类的同义词(如果CF == 1则跳转),但上/下具有正确的语义含义,因此可以减少使代码具有人类可读性所需的注释量。

您可以在jp之类的条件之前跳过ja,因为CF = 0意味着PF = 0。 (即如果操作数是无序的,a条件将为假。对于无序操作数,某些其他条件(如ae)将为真,因此您需要在jp之前或之后分支如果您需要排除NaN输入,请jae

历史兴趣/为何这样设计:

请注意,comisd的标记设置与您从x87 fcom / fnstsw ax / sahf获得的内容相匹配。另见this x87 tutorial/guide for an example of using that sequence。但仅限于历史兴趣! fcomi,也以相同的方式设置标志,已存在超过20年(P6),并且更快。 (有关更多链接,请参阅标记wiki。)

x87仅对80位扩展精度有用,因为即使在32位模式下,也可以安全地假设SSE2可用。

答案 1 :(得分:3)

这里有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标志是否设置 - 如果是,它可以少于关系或无序

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

答案 2 :(得分:2)

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

大于:ZF:0,PF:0,CF:0

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

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

因此,要测量XMM0是否小于XMM4,您需要进行JC。

相信这有帮助。