我试图了解如何使用xmm寄存器比较两个浮点数(32位)。 为了测试我在C中编写了这段代码(在程序集中调用代码):
#include "stdio.h"
extern int compare();
int main()
{
printf("Result: %d\n", compare());
return 0;
}
这是装配,我想测试b< c,在这种情况下确实如此 并且代码应返回1,但它返回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它返回1,但我认为它应该相反,xmm0小于xmm1。
如果我写
movss xmm0, [b]
comiss xmm0, [b]
je change
按预期返回1。 有人知道它为什么会以这种方式行事吗?也许我没有使用正确的跳转说明。
答案 0 :(得分:5)
您想要使用JB和JA(跳过下方/上方)指令而不是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。