xmm, cmp 两个 32 位浮点数

xmm, cmp two 32-bit float

我正在尝试了解如何使用 xmm 寄存器比较两个浮点数(32 位)。 为了测试,我用 C 语言编写了这段代码(调用汇编中的代码):

#include "stdio.h"

extern int compare();

int main()
{

    printf("Result: %d\n", compare());

    return 0;
}

这是程序集,我想测试是否 b < c,在这种情况下它确实如此 并且代码应该 return 1,但它 returns 0:

section .data

a:  dd 5.5555
b:  dd 1.1111
c:  dd 5.5555

section .text

global compare

compare:
            ; -------------------------------------------
            ; Entrace sequence
            ; -------------------------------------------
            push    ebp         ; save base pointer
            mov     ebp, esp    ; point to current stack frame 
            push    ebx         ; save general registers
            push    ecx
            push    edx
            push    esi         
            push    edi

            movss xmm0, [b]
            movss xmm1, [c]
            comiss xmm0, xmm1
            jl change
            mov eax, 0
            jmp end
change:
            mov eax, 1
end:
            ; ------------------------------------------
            ; Exit sequence
            ; ------------------------------------------

            pop     edi
            pop     esi
            pop     edx
            pop     ecx
            pop     ebx
            mov     esp, ebp
            pop     ebp
            ret

如果我尝试使用jg它returns 1,但我认为应该相反,xmm0小于xmm1。

如果我写

movss xmm0, [b]
comiss xmm0, [b]
je change

它return 1,符合预期。 有人知道为什么它会这样吗?也许我没有使用正确的跳转指令。

您想使用 JB 和 JA(跳转 below/above)指令而不是 JL/JG。 COMISS 指令设置标志,就好像它是两个正在比较的无符号整数。这使得对标志的影响更简单。

COMISS 指令对标志的影响在 Intel 64 和 IA-32 架构软件开发人员手册中记录为:

RESULT ← OrderedCompare(SRC1[31:0] ≠ SRC2[31: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; }

虽然分支指令记录为:

77 cb    JA rel8   ...   Jump short if above (CF=0 and ZF=0).
72 cb    JB rel8   ...   Jump short if below (CF=1).
7F cb    JG rel8   ...   Jump short if greater (ZF=0 and SF=OF).
7C cb    JL rel8   ...   Jump short if less (SF≠ OF).

JB/JA测试根据操作结果设置的标志,而JL/JG测试始终设置为0的标志。