内联部件中的双精度数字(GCC,IA-32)

内联部件中的双精度数字(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' ~ $ 我不确定我是否做得对

我刚刚开始学习汇编,我想使用指定的舍入模式对浮点值进行舍入。我已经尝试使用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;
}

我是否已经接近正确的程度了?

更好的方法是编写一个简单的函数,对浮点值进行舍入。接下来,指示编译器打印函数的程序集列表。您可能希望将函数放在一个单独的文件中

这个过程将向您展示编译器使用的调用和退出约定。通过将函数放在单独的文件中,您不必构建其他文件。此外,它还将为您提供用汇编语言函数替换C语言函数的机会


虽然支持内联汇编,但我更喜欢用汇编语言替换整个函数,而不使用内联汇编内联汇编是不可移植的,因此在移植到其他平台时必须更改源代码。

GCC的内联汇编语法至少可以说是晦涩难懂的,我也不自称是专家,但是当我使用它的时候,我使用了它。在所有示例中,所有模板标记的形式都是%n,其中n是一个数字,而不是您使用的%[ttt]形式


我还注意到,错误消息中报告的行号似乎与您发布的代码不一致。所以我想知道他们是否真的是为了这个确切的代码?

你的一个同学已经问过了。在用一个常量fldcw替换旧控制字之后立即使用fstcw是没有意义的。您也从未将n加载到x87 FPU中。内联asm是一种可怕的方式,所以我不会花时间写一个完整的答案。只要使用lrintn之类的东西,%[identifier]的用法似乎是正确的。它使代码更具可读性。您可以使用标识符而不是%s。两种方法都同样有效,其中一种更具可读性。另一个优点是,您可以对约束进行重新排序,而不用担心对模板中的所有引用重新编号。