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

时间:2010-02-21 04:28:19

标签: c assembly

我刚开始学习汇编,我想使用指定的舍入模式舍入浮点值。我尝试使用fstcwfldcwfrndint来实现这一点。

现在我收到了一些错误:

~ $ 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;
}

我是否能够做到这一点?

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

GCC的内联汇编语法至少可以说是神秘的,我并不认为自己是专家,但是当我使用它时,我使用了this howto guide。在所有示例中,所有模板标记的格式为%n,其中n是数字,而不是您使用的%[ttt]形式。

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