内联部件中的双精度数字(GCC,IA-32)
我刚刚开始学习汇编,我想使用指定的舍入模式对浮点值进行舍入。我已经尝试使用fstcw、fldcw和frndint来实现这一点 现在我发现了几个错误:内联部件中的双精度数字(GCC,IA-32),c,assembly,C,Assembly,我刚刚开始学习汇编,我想使用指定的舍入模式对浮点值进行舍入。我已经尝试使用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' ~ $ 我不确定我是否做得对
~ $ 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;
}
我是否已经接近正确的程度了?更好的方法是编写一个简单的函数,对浮点值进行舍入。接下来,指示编译器打印函数的程序集列表。您可能希望将函数放在一个单独的文件中 这个过程将向您展示编译器使用的调用和退出约定。通过将函数放在单独的文件中,您不必构建其他文件。此外,它还将为您提供用汇编语言函数替换C语言函数的机会
虽然支持内联汇编,但我更喜欢用汇编语言替换整个函数,而不使用内联汇编内联汇编是不可移植的,因此在移植到其他平台时必须更改源代码。GCC的内联汇编语法至少可以说是晦涩难懂的,我也不自称是专家,但是当我使用它的时候,我使用了它。在所有示例中,所有模板标记的形式都是%n,其中n是一个数字,而不是您使用的%[ttt]形式
我还注意到,错误消息中报告的行号似乎与您发布的代码不一致。所以我想知道他们是否真的是为了这个确切的代码?你的一个同学已经问过了。在用一个常量fldcw替换旧控制字之后立即使用fstcw是没有意义的。您也从未将n加载到x87 FPU中。内联asm是一种可怕的方式,所以我不会花时间写一个完整的答案。只要使用lrintn之类的东西,%[identifier]的用法似乎是正确的。它使代码更具可读性。您可以使用标识符而不是%s。两种方法都同样有效,其中一种更具可读性。另一个优点是,您可以对约束进行重新排序,而不用担心对模板中的所有引用重新编号。