我本质上要做的就是完成Main工作中的内容。

我正在完成此任务的最后一部分(可能要花很长时间才能到达这里),我在弄清楚如何传递传递给roundD的roundingMode并在ASM中使用它时遇到了麻烦。

而且,据我所知,这只是我要做的一小部分。听起来对吗?

#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)
{
// do not change anything above this comment

    int             oldCW = 0x0000;
    int             newCW = 0xF3FF;
    int             mask  = 0x0300;
    int             tempVar = 0x0000;


    asm("   push    %eax                            \n"
        "   push    %ebx                            \n"
        "   fstcw   %[oldCWOut]                     \n"     //store FPU CW into OldCW
        "   mov     %%eax, %[oldCWOut]              \n"     //store old FPU CW into tempVar
        "   mov     %[tempVarIn], %%eax             \n"
        "   add     %%eax, %[maskIn]                \n"     //isolate rounding bits
        "   add     %%eax, %[roundModeOut]          \n"     //adding rounding modifier
                                                            //shift in old bits to tempFPU
                                                            //do rounding calculation
                                                            //store result into n
        "   fldcw   %[oldCWIn]                      \n"     //restoring the FPU CW to normal
        "   pop     %ebx                            \n"
        "   pop     %eax                            \n"

        :   [oldCWOut]      "=m"    (oldCW),
            [newCWOut]      "=m"    (newCW),
            [maskOut]       "=m"    (mask),
            [tempVarOut]    "=m"    (tempVar),
            [roundModeOut]  "=m"    (roundMode)

        :   [oldCWIn]       "m"     (oldCW),
            [newCWIn]       "m"     (newCW),
            [maskIn]        "m"     (mask),
            [tempVarIn]     "m"     (tempVar),
            [roundModeIn]   "m"     (roundMode)
        :"eax", "ebx"
    );

return n;

// do not change anything below this comment, except for printing out your name
}

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可能会假装枚举不只是一个整数,它还是一个整数。如果您不能在程序集中直接使用roundingMode,请创建一个整数局部变量并将其设置为与roundingMode参数相等。

我只是向您提供建议。我以前从未使用过内联汇编,也从未使用过x86汇编,但是如果您需要做的就是引用该参数,那么我上面所说的应该可以。

09-25 15:34