views:

167

answers:

7

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'
~ $
+1  A: 

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;
}
Scott Smith
return (n < 0.0) ? -n : n;
pm100
This is a homework assignment. I need to do this in assembly. i dont want someone to do it for me. I just need some guidance on what to do
Corey
`#define absD fabs`
KennyTM
+1  A: 

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.

icktoofay
+2  A: 
asm("   fld     %eax \n"  
"   movl    $0x7FFFFFFFFFFFFFFF,  %eax    \n"    
"   pop     %eax     \n"

};

notice the curley bracket before the semicolon.

John Boker
hey, i fixed the curly brace and posted the new error message
Corey
+1  A: 

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?

mctylr
This is a homework assignment. I need to do this in assembly. i dont want someone to do it for me. I just need some guidance on what to do.
Corey
Then it SHOULD be tagged HOMEWORK.
mctylr
+1  A: 

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.

Chris Dodd
How do i load the floating point then?
Corey
+1  A: 

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.

John Knoeller
A: 

/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.

Jens Björnhager