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'开发者_JAVA技巧
~ $
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;
}
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.
asm(" fld %eax \n"
" movl $0x7FFFFFFFFFFFFFFF, %eax \n"
" pop %eax \n"
};
notice the curley bracket before the semicolon.
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?
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.
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.
/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.
精彩评论