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