Author Topic: Testing two 64-bit words for equality  (Read 8958 times)

nobody

  • Guest
Testing two 64-bit words for equality
« on: March 14, 2009, 05:08:39 AM »
Hi,

I'm using the function below to test two 64-bit words for bit equality, returning zero only if they are equal. While it SEEMS to work fine for integers and characters, it drops the ball when it comes to reals (floats), finding 1.0 and -1.0 to be equal, where it XORs the two words that (bit) agree in everything but the sign bit, yielding a result of -0.0, which unfortunately says they're equal. Since the function may be given not only pairs of integers, characters, or reals to compare, but also combinations of these types (integer to real, real to character, etc.), I probably don't want to get too far from what I have. After the XORing, if the sign bit of the result is 1 then the signs had to be different, implying inequality. Then again, I could test sign bits higher up in the function, skipping the XOR altogether if they're different. Then there's always good old subtraction, but when the input parameters can be just about anything 64-bit, how to know whether to do an integer or float subtract? Suggestions welcome.

Michael

======================

global equal_

section  .text ;return 0 only if two (64-bit) parameters are equal

equal_:

push  ebp
  mov   ebp, esp
  mov   eax, [ebp+8]         ;eax <- addr of 1st param
   mov      ecx, [ebp+12]         ;ecx <- addr of 2nd param
  pop      ebp
   mov      edx, [eax+4]         ;edx <- hi dword of 1st param
  mov   eax, [eax]            ;eax <- lo dword of 1st param
   xor      eax, [ecx]            ;xor 1st and 2nd params
   xor      edx, [ecx+4]
   push   edx
   push   eax
   fld qword  [esp]
   add      esp, 8
  ret

nobody

  • Guest
Re: Testing two 64-bit words for equality
« Reply #1 on: March 14, 2009, 04:25:47 PM »
I did the rewrite below and it catches all the cases, but I'm still open to suggestions.

Michael

===============

global equal_

section  .text ;return 0 only if two (64-bit) parameters are equal

equal_:

push  ebp
mov   ebp, esp
mov   eax, [ebp+8]      ;eax <- addr of 1st param
mov   ecx, [ebp+12]      ;ecx <- addr of 2nd param
pop   ebp

mov   edx, [eax+4]      ;edx <- hi dword of 1st param
mov   eax, [eax]         ;eax <- lo dword of 1st param

cmp   eax, [ecx]
jne   .uneql
cmp   edx, [ecx+4]
jne   .uneql
mov   edx, 0            ;equal: return 0
mov   eax, 0
jmp short .done
.uneql:
mov   edx, 0xffffffff   ;unequal: return unzero
mov   eax, 0xffffffff

.done:
push    edx
push   eax
fld qword  [esp]
add   esp, 8
ret

nobody

  • Guest
Re: Testing two 64-bit words for equality
« Reply #2 on: March 14, 2009, 04:53:31 PM »
Comparing floats for equality is a horrid rat's nest!

http://teaching.idallen.com/cst8110/97s/floating_point.html

Apart from that, doesn't your routine blow the FPU stack after you call it a few times? Or does the caller pop the FPU stack?

"how to know whether to do an integer or float subtract?" Same way you know whether to use an integer xor or a float xor, I guess. (that's a joke!)

Do I understand you hope to compare a 64-bit int and a 64-bit float for equality? I don't see how that's going to be useful. The bit representations are completely different (except 0 = 0.0... but not -0.0).

If "exact bitwise equality" of two floats is useful to you, the xor should work. I don't see what you're gaining by loading the result onto the FPU stack.

Best,
Frank

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Testing two 64-bit words for equality
« Reply #3 on: March 14, 2009, 05:56:16 PM »
Okay, apparently Fortran *does* pop the FPU stack after the call (dunno how it knows to do that, but it does), so you're okay... Never mind...

Best,
Frank