0

Sorry for the elementary question.

In assembly is it acceptable to compare two floating points stored at different (fixed) memory locations without loading them into the stack? Do I need to use anything besides CMP and JLE?

E.g. Memory address [A] currently equals 95, memory address [B] equals [90]. I want to do a jump if [A] is less than or equal to 90. Is the following sufficient?

CMP DWORD PTR [A], CMP DWORD PTR [B]
JLE [Another address]
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • No that is not valid, and no, that is not even a floating point comparison. – Jester Jan 21 '23 at 15:56
  • 3
    For context, can you say what level of CPU/FPU you are programming for? Are you retrocomputing for a classic 8087, 80287, Pentium? Or do you have a computer from the last 20 years that has SSE? The standard way to do a floating point compare varies among these. (But none of them can compare two memory operands. And `cmp` does integer comparisons, which are not correct for floating point, so a different instruction is needed.) – Nate Eldredge Jan 21 '23 at 16:24
  • Nate, it's an x87 executable from 1998 – x87-Learner Jan 22 '23 at 00:06

1 Answers1

2

If both floats are positive, and you don't care about issues like NAN:

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

If either float can be negative, but not negative zero (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     ...

Negative 0 will end up 07fffffffh, less than positive 0 which ends up 080000000h. If this is an issue, the code would need to be modified.

rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • Thank you! Both floats are positive. The actual floats are between 1 and 0 so could be considered normalised? Just a quick question though. Does MOV EAX/EBX overwrite the EAX/EBX value, or is it the equivalent of doing a PUSH? If the original EAX or EBX value is needed before and after this little loop should I do a push and pop? – x87-Learner Jan 22 '23 at 00:15
  • 1
    @user1708538 "normalized" means a non-zero exponent field. Magnitude >= `FLT_MIN`. Subnormal aka denormal floats have an exponent encoded as zero, implying a leading `0` bit in the mantissa. `FLT_MIN > |x| >= FLT_TRUE_MIN`. Knowing that values are between 1 and 0 doesn't rule out subnormals. – Peter Cordes Jan 22 '23 at 01:41
  • 2
    @user1708538: **However, you don't actually need your floats to be normalized for integer comparison to work, just not NaN.** Doing an integer Increment on the bit-pattern monotonically increases the magnitude of the value represented by the float up from zero to Infinity; this is how `nextafterf(x, Infinity)` works. – Peter Cordes Jan 22 '23 at 01:42
  • 1
    @user1708538: Yes, of course this overwrites whichever registers you use. Pick registers that aren't in use, save/restore them somewhere, or use x87 or SSE registers with `fcomi` (P6) or [`ucomiss` (SSE1)](https://www.felixcloutier.com/x86/ucomiss) respectively if the integer registers are all in use. – Peter Cordes Jan 22 '23 at 01:44
  • Peter, whenever I have asked a question here, you have always been a great help. Thank you. This memory address will always be *a* number of some kind, but what if it is 00000000? In that case, I presume "0" will be moved to EAX? Then I can do a test eax, eax ? – x87-Learner Jan 22 '23 at 02:39
  • 1
    @x87-Learner: yes, the bit-pattern for 0.0 is `0x00000000`. https://www.h-schmidt.net/FloatConverter/IEEE754.html and https://en.wikipedia.org/wiki/Single-precision_floating-point_format . And yes, comparing a single number against zero is even easier with integer compares, that always Just Works except for NaN, so `cmp dword [a], 0` (or load and `test eax,eax`) / `jle less_or_equal_to_zero`. Negative zero gets treated as negative, not zero, but that's ok with jle or jg, but not je or jl (or jge). – Peter Cordes Jan 22 '23 at 03:10
  • Peter, I just tried it with cmp dword [a], 0 and it is all working exactly as intended. Many, many thanks! – x87-Learner Jan 22 '23 at 04:00
  • @EricPostpischil - Answer should be fixed now. – rcgldr Jan 22 '23 at 04:30
  • Related: [Compare floating point numbers as integers](https://stackoverflow.com/q/33678827) for another mapping from FP bit-pattern to comparable-integer. – Peter Cordes Feb 02 '23 at 18:27