1

我经常使用/QIfist编译器开关,这会导致编译器生成FISTP将浮点值舍入为整数的指令,而不是调用_ftol辅助函数。

我怎样才能让它使用FIST(P) DWORD,而不是QWORD

FIST QWORD要求 CPU 将结果存储在堆栈中,然后将堆栈读取到寄存器中,最后存储到目标内存中,而FIST DWORD直接存储到目标内存中。

4

1 回答 1

0

FIST QWORD 要求 CPU 将结果存储在堆栈中,然后将堆栈读入寄存器,最后存储到目标内存中,而 FIST DWORD 只是直接存储到目标内存中。

我不明白你在这里想说什么。和指令
在两个方面彼此不同:FISTFISTP

  1. FISTP 从浮点堆栈中弹出顶部值,而FIST不会。这是明显的区别,并反映在操作码命名中:FISTP有那个P后缀,意思是“pop”,就像ADDP等。

  2. 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;
}
于 2014-08-02T09:15:09.093 回答