我可以比较两个浮点数而不将它们加载到 x87 堆栈上吗?

Can I compare two floats without loading them on the x87 stack?

提问人:x87-Learner 提问时间:1/21/2023 最后编辑:Peter Cordesx87-Learner 更新时间:1/22/2023 访问量:93

问:

对不起,这个基本问题。

在汇编中,是否可以比较存储在不同(固定)内存位置的两个浮点,而不将它们加载到堆栈中?除了 CMP 和 JLE 之外,我还需要使用任何东西吗?

例如,内存地址 [A] 当前等于 95,内存地址 [B] 等于 [90]。如果 [A] 小于或等于 90,我想跳转。以下条件就足够了吗?

CMP DWORD PTR [A], CMP DWORD PTR [B]
JLE [Another address]
程序集 x86 浮点

评论

0赞 Jester 1/21/2023
不,这是无效的,不,这甚至不是浮点比较。
3赞 Nate Eldredge 1/22/2023
对于上下文,您能说出您正在针对哪个级别的 CPU/FPU 进行编程吗?您是否正在为经典的 8087、80287、Pentium 进行逆向计算?或者你有一台过去 20 年有 SSE 的计算机吗?执行浮点比较的标准方法各不相同。(但是他们都无法比较两个内存操作数。并且进行整数比较,这对于浮点数不正确,因此需要不同的指令。cmp
0赞 x87-Learner 1/22/2023
Nate,它是 1998 年的 x87 可执行文件

答:

2赞 rcgldr 1/22/2023 #1

如果两个浮点数都是正数,并且您不关心 NAN 之类的问题:

        mov     eax,[a]
        cmp     eax,[b]
        jbe     ...

如果任一浮点数可以为负数,但不能为负零 (080000000h):

        mov     eax,[a]
        cmp     eax,[b]
        mov     ecx,eax
        sar     ecx,31
        or      ecx,080000000h
        xor     eax,ecx
        mov     ecx,ebx
        sar     ecx,31
        or      ecx,080000000h
        xor     ebx,ecx
        cmp     eax,ebx
        jbe     ...

负 0 最终将得到 07fffffffh,小于正 0,最终得到 080000000h。如果这是一个问题,则需要修改代码。

评论

0赞 x87-Learner 1/22/2023
谢谢!两个浮点数都是正的。实际浮点数介于 1 和 0 之间,因此可以认为是标准化的吗?不过只是一个简短的问题。MOV EAX/EBX 是否覆盖 EAX/EBX 值,或者是否等同于执行 PUSH?如果在这个小循环之前和之后需要原始的 EAX 或 EBX 值,我应该做一个推和弹出吗?
1赞 Peter Cordes 1/22/2023
@user1708538“归一化”是指非零指数场。星等 >= 。次正态(又名非正态浮点数)的指数编码为零,表示尾数中的前导位。.知道值介于 1 和 0 之间并不排除次正常值。FLT_MIN0FLT_MIN > |x| >= FLT_TRUE_MIN
2赞 Peter Cordes 1/22/2023
@user1708538:但是,您实际上并不需要对浮点数进行归一化才能进行整数比较,只是不需要 NaN。对位模式执行整数 Increment 单调地将浮点数所表示的值的大小从零增加到无穷大;这就是工作原理。nextafterf(x, Infinity)
1赞 Peter Cordes 1/22/2023
@user1708538:是的,当然,这会覆盖您使用的任何寄存器。选择未使用的寄存器,将它们保存/还原到某个位置,或者如果整数寄存器都在使用中,则分别将 x87 或 SSE 寄存器与 (P6) 或 ucomiss (SSE1) 一起使用。fcomi
1赞 Peter Cordes 1/22/2023
@x87-Learner:是的,0.0 的位模式是 。h-schmidt.net/FloatConverter/IEEE754.htmlen.wikipedia.org/wiki/Single-precision_floating-point_format。是的,使用整数比较将单个数字与零进行比较甚至更容易,除了 NaN 之外,它总是有效,所以(或加载和)/ 。负零被视为负数,而不是零,但这对 jle 或 jg 来说是可以的,但对 je 或 jl(或 jge)来说不是。0x00000000cmp dword [a], 0test eax,eaxjle less_or_equal_to_zero