C 在装配中使用frndint进行四舍五入

C 在装配中使用frndint进行四舍五入,c,gcc,assembly,inline-assembly,att,C,Gcc,Assembly,Inline Assembly,Att,我试图将一个浮点n传递到ebx(或者如果可以,只需使用n)并对其进行舍入,然后将其传递回n并将值返回到main,这段代码运行4次,每次传递一个不同的舍入模式值,该值修改FPU控制字的舍入计数位 问题是,无论我通过什么,它都不会绕过任何东西。我查看了IA-32手册,上面说FRNDINT会对堆栈中的第一项进行取舍,这就是我将ebx推到堆栈上的原因 当我在GDB中运行我的代码时,我可以看到在frndint命令中,它将疯狂的值放入ebx中 asm(" push %%ebx

我试图将一个浮点n传递到ebx(或者如果可以,只需使用n)并对其进行舍入,然后将其传递回n并将值返回到main,这段代码运行4次,每次传递一个不同的舍入模式值,该值修改FPU控制字的舍入计数位

问题是,无论我通过什么,它都不会绕过任何东西。我查看了IA-32手册,上面说FRNDINT会对堆栈中的第一项进行取舍,这就是我将ebx推到堆栈上的原因

当我在GDB中运行我的代码时,我可以看到在frndint命令中,它将疯狂的值放入ebx中

    asm("   push    %%ebx                           \n"
        "   fstcw   %[trueCWIn]                     \n"     //store FPU CW into trueCW
        "   mov     %[nIn], %%ebx                   \n"
        "   mov     %[trueCWOut], %%eax             \n"
        "   add     %[roundingModeOut], %%eax       \n"
        "   frndint                                 \n"     //do rounding calculation
        "   fldcw   %[trueCWIn]                     \n"     //restoring the FPU CW to normal
        "   pop     %%ebx                           \n"

        :   [trueCWOut]     "=m"    (trueCW),
            [tempCWOut]     "=m"    (tempCW),
            [maskOut]       "=m"    (mask),
            [tempVarOut]    "=m"    (tempVar),
            [roundingModeOut]       "=m"    (roundingMode),
            [nOut]          "=m"    (n)

        :   [trueCWIn]      "m"     (trueCW),
            [tempCWIn]      "m"     (tempCW),
            [maskIn]        "m"     (mask),
            [tempVarIn]     "m"     (tempVar),
            [roundingModeIn]        "m"     (roundingMode),
            [nIn]           "m"     (n)
        :"eax", "ebx"
    );
return n;
例如,当n=5.6时,FRNDINT将2.72008302e+23放入ebx

    asm("   push    %%ebx                           \n"
        "   fstcw   %[trueCWIn]                     \n"     //store FPU CW into trueCW
        "   mov     %[nIn], %%ebx                   \n"
        "   mov     %[trueCWOut], %%eax             \n"
        "   add     %[roundingModeOut], %%eax       \n"
        "   frndint                                 \n"     //do rounding calculation
        "   fldcw   %[trueCWIn]                     \n"     //restoring the FPU CW to normal
        "   pop     %%ebx                           \n"

        :   [trueCWOut]     "=m"    (trueCW),
            [tempCWOut]     "=m"    (tempCW),
            [maskOut]       "=m"    (mask),
            [tempVarOut]    "=m"    (tempVar),
            [roundingModeOut]       "=m"    (roundingMode),
            [nOut]          "=m"    (n)

        :   [trueCWIn]      "m"     (trueCW),
            [tempCWIn]      "m"     (tempCW),
            [maskIn]        "m"     (mask),
            [tempVarIn]     "m"     (tempVar),
            [roundingModeIn]        "m"     (roundingMode),
            [nIn]           "m"     (n)
        :"eax", "ebx"
    );
return n;

FPU堆栈是FPU(又名寄存器)的内部内存。它是普通堆栈以外的另一种东西,可以用另一种方式访问。frndint使用FPU堆栈还是普通堆栈?引自IA-32手册:“根据当前舍入模式(FPU控制字的RC字段设置),将ST(0)寄存器中的源值舍入为最接近的整数值,并将结果存储在ST(0)中。”它没有指定正常堆栈与FPU堆栈,所以我假设这意味着正常堆栈。FPU对正常堆栈一无所知。如果术语“堆栈”用于FPU指令,则它始终是FPU堆栈。阅读IA-32手册第1卷第8章或更好的教程:在frndint之前,我仅有的与FPU相关的指令是fstcw,据我所知,它对FPU堆栈没有任何作用。你是对的,它没有。这就是你的代码不起作用的原因。举例来说,如果您只想使用当前舍入模式进行舍入,可以执行如下操作:asm(“frndint”:“+t”(n));要了解“+t”的作用,请查看gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html上的“英特尔386”部分中的“t”,并查看gcc.gnu.org/onlinedocs/gcc/Modifiers.html中的“+”。问题的其余部分留给学生做练习。我猜你就是这样。FWIW,我用4行asm,3个参数,0个clobbers解决了这个问题。你可能有点想过头了。