我刚开始学习汇编,我想使用指定的舍入模式舍入浮点值。我尝试使用fstcw
,fldcw
和frndint
来实现这一点。
现在我收到了一些错误:
~ $ gc a02p
gcc -Wall -g a02p.c -o a02p
a02p.c: In function `roundD':
a02p.c:33: error: parse error before '[' token
a02p.c:21: warning: unused variable `mode'
~ $
我不确定我是否正在做这件事。我不想使用任何预定义的功能。我想使用GCC内联汇编。
这是代码:
#include <stdio.h>
#include <stdlib.h>
#define PRECISION 3
#define RND_CTL_BIT_SHIFT 10
// floating point rounding modes: IA-32 Manual, Vol. 1, p. 4-20
typedef enum {
ROUND_NEAREST_EVEN = 0 << RND_CTL_BIT_SHIFT,
ROUND_MINUS_INF = 1 << RND_CTL_BIT_SHIFT,
ROUND_PLUS_INF = 2 << RND_CTL_BIT_SHIFT,
ROUND_TOWARD_ZERO = 3 << RND_CTL_BIT_SHIFT
} RoundingMode;
double roundD (double n, RoundingMode roundingMode)
{
short c;
short mode = (( c & 0xf3ff) | (roundingMode));
asm("fldcw %[nIn] \n"
"fstcw %%eax \n" // not sure why i would need to store the CW
"fldcw %[modeIn] \n"
"frndint \n"
"fistp %[nOut] \n"
: [nOut] "=m" (n)
: [nIn] "m" (n)
: [modeIn] "m" (mode)
);
return n;
}
int main (int argc, char **argv)
{
double n = 0.0;
if (argc > 1)
n = atof(argv[1]);
printf("roundD even %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_NEAREST_EVEN));
printf("roundD down %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_MINUS_INF));
printf("roundD up %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_PLUS_INF));
printf("roundD zero %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_TOWARD_ZERO));
return 0;
}
我是否能够做到这一点?
答案 0 :(得分:0)
更好的过程是编写一个对浮点值进行舍入的简单函数。接下来,指示编译器打印函数的程序集列表。您可能希望将该函数放在单独的文件中。
此过程将向您显示编译器使用的调用和退出约定。通过将函数放在单独的文件中,您不必构建其他文件。此外,它还为您提供了使用汇编语言函数替换C语言函数的机会。
虽然支持内联汇编,但我更喜欢用汇编语言替换整个函数而不使用内联汇编(内联汇编不可移植,因此在移植到不同平台时必须更改源代码。)
答案 1 :(得分:0)
GCC的内联汇编语法至少可以说是神秘的,我并不认为自己是专家,但是当我使用它时,我使用了this howto guide。在所有示例中,所有模板标记的格式为%n,其中n是数字,而不是您使用的%[ttt]形式。
我还注意到您的错误消息中报告的行号似乎与您发布的代码不一致。所以我想知道它们是否真的是这个确切的代码?