绝对值双倍

时间:2010-02-12 01:32:46

标签: c assembly

我正在尝试编写一个名为absD的函数,它返回其参数的绝对值。 我不想使用任何预定义的功能。现在我在尝试编译时遇到解析错误。

我想成像所有我必须要做的是获得双倍的绝对值是改变符号位?这就是我所拥有的

#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;
}

我修好了大括号.. 我得到的错误是

~ $ 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'
~ $

7 个答案:

答案 0 :(得分:1)

你需要在装配中这样做吗?这是一项作业要求,还是您正在寻找非常高的性能?

这不使用任何预定义的功能:

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

    return n;
}

答案 1 :(得分:1)

我不是专家,但看起来你正在使用(来打开程序集块而}来结束它。你可能应该使用其中一个,而不是两个都不一致。

答案 2 :(得分:1)

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

};

注意分号前的花括号。

答案 3 :(得分:1)

根据您希望如何处理-0.0,您可以使用C99 / POSIX(2004)的signbit()功能。

#include <math.h>

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

但坦率地说,如果您使用标准C库(libc)atof和printf,我不明白为什么不使用fabs()是可取的。你也可以在C中做正常的比特纠缠。

当然,如果您正在使用汇编,为什么不使用fchs op?

答案 4 :(得分:1)

汇编代码中存在错误,汇编程序会为您提供完全合理的错误消息。

  • 您无法直接从%eax加载浮点值 - 操作数需要是要加载的地址

  • 你不能有不适合32位的常量文字。

答案 5 :(得分:1)

浮点位的符号只是高位,所以你需要清除最重要的位。

如果你必须在汇编中这样做,那么在我看来你最好使用整数而不是浮点指令。您不能对浮点寄存器执行按位操作。

此外,没有必要将整个8字节值加载到任何寄存器中,如果处理器没有8字节整数寄存器,则只能在高字节(或int)上轻松操作。 / p>

答案 6 :(得分:0)

  

/tmp/ccl2H7rf.s:228:错误:后缀或   操作数对于'fld'

无效

fld需要操作数在内存中。把它放在内存中,即堆栈中,并提供地址。

  

/tmp/ccl2H7rf.s:229:错误:缺少或   立即表达无效   `0x7FFFFFFFF FFFFFFF'

EAX不超过32位。如果您认为这是一个浮点数,请将其放在带有加载指令的浮点堆栈上,即fld。