Steller
Steller

Reputation: 308

absolute Value of double

I am trying write a function named absD that returns the absolute value of its argument. I do not want to use any predefined functions. Right now i am getting a parse error when i try to compile it.

I would image all i would have to do to get the absolute value of a double is change the sign bit? this is what i have

#include <stdio.h>
#include <stdlib.h>

#define PRECISION   3

double absD (double n)
{

asm("   fld     %eax \n"  
    "   movl    $0x7FFFFFFFFFFFFFFF,  %eax    \n"    
    "   pop     %eax     \n"

    );

return n;


}

int main (int argc, char **argv)
{
double  n = 0.0;

printf("Absolute value\n");
if (argc > 1)
    n = atof(argv[1]);

printf("abs(%.*f) = %.*f\n", PRECISION, n, PRECISION, absD(n));

return 0;
}

I fixed the curly brace.. the error i am getting is

~ $ gc a02
gcc -Wall -g a02.c -o a02
/tmp/ccl2H7rf.s: Assembler messages:
/tmp/ccl2H7rf.s:228: Error: suffix or operands invalid for `fld'
/tmp/ccl2H7rf.s:229: Error: missing or invalid immediate expression `0x7FFFFFFFF
FFFFFFF'
~ $

Upvotes: 0

Views: 3883

Answers (7)

Jens Bj&#246;rnhager
Jens Bj&#246;rnhager

Reputation: 5648

/tmp/ccl2H7rf.s:228: Error: suffix or operands invalid for `fld'

fld needs the operand to be in memory. Put it in memory, ie the stack, and supply the address.

/tmp/ccl2H7rf.s:229: Error: missing or invalid immediate expression `0x7FFFFFFFF FFFFFFF'

EAX does not hold more than 32 bits. If you meant for this to be a floating point number, put it on the floating point stack with a load instruction, ie fld.

Upvotes: 0

John Knoeller
John Knoeller

Reputation: 34188

The sign of a floating bit number is just the high bit, so all you need to to is clear the most significant bit.

If you must do this in assembly, then it seems to me that you would be better of using integer rather than floating point instructions. You can't do bitwise operations on floating point registers.

Also, there isn't any need to load the entire 8 byte value into any register, you could just as easily operate only on the high byte (or int) if your processor doesn't have 8 byte integer registers.

Upvotes: 1

Chris Dodd
Chris Dodd

Reputation: 126448

You have errors in your assembly code, which the assembler gives you perfectly reasonable error messages about.

  • you can't load a floating point value directly from %eax -- the operand needs to be an address to load from

  • you can't have constant literals that don't fit in 32 bits.

Upvotes: 1

mctylr
mctylr

Reputation: 5169

Depending on how you want to treat -0.0, you can use C99 / POSIX (2004)'s signbit() function.

#include <math.h>

double absD (double x)
{
     if ( signbit(x) ) {
#ifdef NAIVE
         return 0.0 - x;
#else
         return x &= 0x7FFFFFFFFFFFFFFF;
#endif
     } else {
         return x;
     }
}

But frankly if you're using Standard C Library (libc) atof and printf, I don't see why not using fabs() is desirable. As you can also do normal bit-twiddling in C.

Of course if you're using assembly, why not usefchs op anyhow?

Upvotes: 1

John Boker
John Boker

Reputation: 83729

asm("   fld     %eax \n"  
"   movl    $0x7FFFFFFFFFFFFFFF,  %eax    \n"    
"   pop     %eax     \n"

};

notice the curley bracket before the semicolon.

Upvotes: 1

icktoofay
icktoofay

Reputation: 129109

I'm no expert, but it looks like you're using ( to open the assembly block and } to end it. You probably should use one or the other, not both inconsistently.

Upvotes: 1

Scott Smith
Scott Smith

Reputation: 3986

Do you need to do it in assembly? Is this a homework requirement, or are you looking for very high performance?

This doesn't use any predefined functions:

double absD(double n)
{
    if (n < 0.0)
        n = -n;

    return n;
}

Upvotes: 1

Related Questions