assembly 是否应该始终从x87 FPU堆栈中弹出值?

cdmah0mi  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(95)

最近,我一直在真实的模式下用x86汇编编写一些数学代码。这些代码在模拟器和真实的硬件上都进行了测试。我假设,在我的数学函数中,我可以简单地将不再需要的剩余值留在fpu堆栈上,以便下一个函数,随着其fpu负载,将使这些旧值最终从堆栈中消失。代码,以这种方式编写的代码在qemu中按预期工作,但在真实的硬件上,fpu寄存器堆栈中的值被损坏,但没有任何一致性。我重写了我的代码,因此,在我的任何函数中,所有值都从fpu堆栈中弹出,即任何函数获得其拥有的空FPU栈或具有其自变量的FPU栈并使FPU栈为空或具有ST0中的返回值,它应该返回它在FPU寄存器中的值。我的代码开始工作,因为我期望它在QEMU和真实的硬件上都能工作。
是否有一个规则,我错过了关于FPU堆栈溢出,或者换句话说,值从FPU堆栈上掉下来?

oxcyiej7

oxcyiej71#

如果在x87堆栈中留下不需要的值,(除了使用该链接约定时ST 0中的结果外)然后在几次调用你的例程后,堆栈溢出将发生。基本上你只有8个插槽在x87堆栈上使用,一旦它们都满了,下一个FP加载将失败。你只能加载一个值到空寄存器,然后成为新的堆栈顶部。这是最好的做法就是保持原样
MASM论坛上的这个Simply FPU article是对x87及其怪癖的一个不错的介绍。
有大量的指令沿着行:“做一些事情并弹出堆栈”,或者在某些情况下“弹出堆栈两次”。所以确保不需要的值不会留在堆栈上不是一个大问题。
例如,浮点比较有3种类型:

  • FCOM -堆栈未更改
  • FCOMP - ST(0)弹出
  • FCOMPP - ST(0)& ST(1)弹出

您还可以使用FFREE显式地将堆栈寄存器设置为空(尽管我不记得曾经见过任何FP代码这样做)。
如果你愿意的话,你可以手动增加和减少FP堆栈指针,但这是另一个我不记得曾经见过使用过的功能(有人在这里吗?)。
曾经有一段时间,人们会手工编写FFT内核来保持x87堆栈上的递归关系,任何不小心的编码错误都会溢出堆栈。
值得注意的是,新的SIMD FP指令比x87代码快得多,所以除非你在练习中这样做,否则让编译器使用HLL中的SSE 2、AVX或AVX 2 FP代码可能会更好。

相关问题