AR8*_*R89 0 floating-point assembly sse
我试图了解如何使用xmm寄存器比较两个浮点数(32位).为了测试我在C中编写了这段代码(在程序集中调用代码):
#include "stdio.h"
extern int compare();
int main()
{
printf("Result: %d\n", compare());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是程序集,我想测试是否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
Run Code Online (Sandbox Code Playgroud)
如果我尝试使用jg它返回1,但我认为它应该相反,xmm0小于xmm1.
如果我写
movss xmm0, [b]
comiss xmm0, [b]
je change
Run Code Online (Sandbox Code Playgroud)
按预期返回1.有人知道它为什么会以这种方式行事吗?也许我没有使用正确的跳转指令.
您想使用JB和JA(跳过下方/上方)指令而不是JL/JG.COMISS指令将标志设置为两个无符号整数进行比较.这使得对标志的影响更简单.
COMISS指令对标志的影响记录在Intel 64和IA-32架构软件开发人员手册中:
Run Code Online (Sandbox Code Playgroud)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; }
虽然分支指令记录为:
Run Code Online (Sandbox Code Playgroud)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.