我正在尝试编写一个名为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'
~ $
答案 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。