我经常使用/QIfist
编译器开关,这会导致编译器生成FISTP
将浮点值舍入为整数的指令,而不是调用_ftol
辅助函数。
我怎样才能让它使用FIST(P) DWORD
,而不是QWORD
?
FIST QWORD
要求 CPU 将结果存储在堆栈中,然后将堆栈读取到寄存器中,最后存储到目标内存中,而FIST DWORD
直接存储到目标内存中。
我经常使用/QIfist
编译器开关,这会导致编译器生成FISTP
将浮点值舍入为整数的指令,而不是调用_ftol
辅助函数。
我怎样才能让它使用FIST(P) DWORD
,而不是QWORD
?
FIST QWORD
要求 CPU 将结果存储在堆栈中,然后将堆栈读取到寄存器中,最后存储到目标内存中,而FIST DWORD
直接存储到目标内存中。
FIST QWORD 要求 CPU 将结果存储在堆栈中,然后将堆栈读入寄存器,最后存储到目标内存中,而 FIST DWORD 只是直接存储到目标内存中。
我不明白你在这里想说什么。和指令
在两个方面彼此不同:FIST
FISTP
FISTP
从浮点堆栈中弹出顶部值,而FIST
不会。这是明显的区别,并反映在操作码命名中:FISTP
有那个P
后缀,意思是“pop”,就像ADDP
等。
FISTP
具有适用于 64 位 ( QWORD
) 操作数的附加编码。这意味着您可以使用FISTP
将浮点值转换为 64 位整数。FIST
另一方面,在 32 位 ( DWORD
) 操作数处达到最大值。
(我认为这没有技术原因。我当然无法想象它与弹出行为有关。我假设当英特尔工程师一段时间后添加对 64 位操作数的支持时,他们认为没有非弹出版本的原因。他们可能用完了操作码编码。)
有很多关于 x86 指令集的在线参考资料。例如,该网站是大多数 Google 搜索的热门网站。或者您可以查看英特尔的手册(FIST
/FISTP
位于第 365 页)。
两条指令从哪里读取值以及将值存储到哪里,是完全相同的。两者都从浮点堆栈的顶部读取值,并将结果存储到内存中。
编译器使用FIST
而不是FISTP
. 请记住,从函数退出时,您总是必须从浮点堆栈中弹出所有值,因此如果FIST
使用了,则必须在其后附加一条FSTP
指令。这可能不会更慢,但它会不必要地夸大代码。
此外,编译器更喜欢的另一个原因是FISTP
:支持 64 位操作数。它允许代码生成器是相同的,无论您四舍五入到什么大小的整数。
您可能更喜欢使用的唯一情况是您正在手写汇编代码并希望在舍入后FIST
重新使用堆栈上的浮点值。编译器不需要这样做。
所以无论如何,所有这一切都表明你的问题的答案是否定的。无法使编译器FIST
自动生成指令。如果您仍然坚持,您可以编写使用您想要的任何指令的内联汇编:
int32 RoundToNearestEven(float value)
{
int32 result;
__asm
{
fld DWORD PTR value
fist DWORD PTR result
// do something with the value on the floating point stack...
//
// ... but be sure to pop it off before returning
fstp st(0)
}
return result;
}