Author Topic: Testing for 0xFFFFFFFFFFFFFFFF  (Read 10358 times)

nobody

  • Guest
Testing for 0xFFFFFFFFFFFFFFFF
« on: December 24, 2008, 03:27:19 AM »
Hi,

This is incomplete but works. It's a function with two qword parameters,
the first must be a number that can be represented in 2 bits (0-3) or a
-1, and the second must be a variable (see calling function below) that
contains some arbitrary number. If the first parameter is a -1, it acts
as a do nothing flag, otherwise the first parameter number is placed in
the highest 2 bits of the second parameter's high dword.

Some examples:
   Input:
      1st param = -1
      2nd param = 256
   Output: 100 (hex) ;unchanged

Input:
      1st param = 1
      2nd param = 256
   Output: 4000000000000100

Input:
      1st param = 2
      2nd param = 256
   Output: 8000000000000100

Input:
      1st param = 3
      2nd param = 256
   Output: C000000000000100

The function will eventually have four parameters,
any of the first three capable of being flagged
with a -1, or having a value which will be inserted
into a reserved field in the final parameter.

Be aware that Fortran, unlike C, passes the addresses
of all function arguments.

My question:
 A -1 is 0xFFFFFFFFFFFFFFFF. Since I must test for
it two more times, is there a nicer way to do it?

Michael

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

global setdir_

section .text      ;

setdir_:
   push   ebp
  mov   ebp, esp
   mov      eax, [ebp+8]
   mov      edx, [ebp+12]
   pop      ebp
   cmp dword  [eax], 0xffffffff      ;if both [eax] & [eax+4] are all 1s goto chngid
   jne      .chngid
   cmp   dword   [eax+4], 0xffffffff
   je      .done
   .chngid:
   and   dword   [edx+4], 0x3fffffff      ;
   mov      ecx, [eax]
   shl      ecx, 30
   or      [edx+4], ecx
   .done:
   ret

Fortran calling program:

integer m

m = 256
      call setdir(3,m)
      print 5, m
    5 format(z20)
      end

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Testing for 0xFFFFFFFFFFFFFFFF
« Reply #1 on: December 24, 2008, 06:34:20 AM »
Hi Michael,

Question on the specification. The 1st parameter must be 0..3 or -1. What do you want to do if it isn't?

If anything over 3 is considered the "do nothing" flag...

global setdir_

section .text      ;

setdir_:
   push   ebp
  mov   ebp, esp
   mov      eax, [ebp+8]
   mov      edx, [ebp+12]
   pop      ebp

mov ecx, [eax]
    cmp ecx, 3
    ja .done

and   dword   [edx+4], 0x3fffffff      ;
   shl      ecx, 30
   or      [edx+4], ecx
   .done:
   ret

If the first parameter is guaranteed to be 0..3 or -1, we can do better. "shl" puts the "evicted" bit in the carry flag, so it'll be "nc" if 0..3 and "c" if -1... or if that bit happens to be set in some "invalid" value. If that helps, do it before the "and" of course. With multiple parameters, shifted different amounts, this probably isn't going to help.

If we really need to check the high dword of the first parameter before we're sure it's a "do nothing flag"... the way you're doing it may be best.

Hmmm... this is the first time I've had any success with Fortran. I tried the example you posted a while ago, and gfortran just yelled at me. ("Unclassifiable Statement" and such, IIRC - a lot of it). This one compiles... or seems to. However... it seems to print "100" no matter what the first parameter is! (using both your original subroutine and my "improved" version). So consider all of the above speculative and unproven! More research required!

Later,
Frank

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Testing for 0xFFFFFFFFFFFFFFFF
« Reply #2 on: December 24, 2008, 07:06:04 AM »
Looks like my gfortran only likes 32-bit "integers"(?). Do I need to do something "special" to tell it 64-bit integers? (doesn't like "long long"). I'm lost, I'm afraid...

Best,
Frank

nobody

  • Guest
Re: Testing for 0xFFFFFFFFFFFFFFFF
« Reply #3 on: December 24, 2008, 01:49:12 PM »
Hi Frank,

Sorry, I probably should have included the Makefile:

callsetdir: callsetdir.o setdir.o
   gfortran callsetdir.o setdir.o -o callsetdir

callsetdir.o: callsetdir.f
   gfortran -c -fdefault-integer-8 -fdefault-real-8 -fno-range-check callsetdir.f -o callsetdir.o

setdir.o: setdir.asm
   nasm -f elf setdir.asm -o setdir.o

By default all integers and reals (C ints & floats) are 64-bit. Addresses are still 32-bit. The no-range-check flag keeps the compiler from griping about integers bigger than will fit in 32-bits.

As I noted in my original post, Fortran passes all function arguments by reference. i.e., you're not getting copies of the values of the parameters (ala C) on the stack but the actual machine addresses (32-bit in this case) of the parameters. It took a bit of getting used to.

Oh, and I almost forgot. Your question about passing a value not equal to -1, 1, 2, or 3 is a valid one. Actually, the first parameter can also be a 0 though that won't change the code. All the values (-1, 0, 1, 2, 3)  are passed as literal  integer constants, not variables, so they will never be anything else.

Merry Christmas!

Michael