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的标志。
我正在尝试了解如何使用 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的标志。