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

问题描述 投票:0回答:1

最近我一直在实模式下用x86汇编编写一些数学代码。该代码在模拟器和真实硬件中都经过了测试。 我假设,在我的数学函数中,我可以简单地将不再需要的剩余值保留在 fpu 堆栈上,这样下一个函数及其 fpu 加载将使这些旧值最终从堆栈中消失。以这种方式编写的代码在 qemu 中按预期工作,但在实际硬件上,fpu 寄存器堆栈中的值被损坏,没有任何一致性。 我重写了我的代码,这样,在我的任何函数中,所有值都会从 fpu 堆栈中弹出,即任何函数都会获得其所拥有的空 fpu 堆栈或带有其参数的 fpu 堆栈,并将 fpu 堆栈留为空或返回值在 st0 中,是否应该返回 fpu 寄存器中的值。我的代码开始按照我的预期在 qemu 和真实硬件上运行。

是否有一条规则,我遗漏了 FPU 堆栈溢出,或者换句话说,值从 FPU 堆栈中掉落?

assembly x86 intel real-mode x87
1个回答
0
投票

如果您在 x87 堆栈上留下不需要的值(除了使用链接约定时 ST0 中的结果),那么在对例程进行几次调用后,就会发生堆栈溢出。基本上,x87 堆栈上只有 8 个插槽可供使用,一旦它们全部填满,下一个 FP 加载就会失败。您只能将值加载到空寄存器中,然后该寄存器将成为新的堆栈顶部。最好始终将其保留在您发现时的原样。

MASM 论坛上的这篇 Simply FPU 文章 对 x87 及其怪癖进行了不错的介绍。

有很多类似做某事并弹出堆栈的指令,或者在某些情况下弹出堆栈两次。因此,确保不需要的值不会留在堆栈中并不是一个大问题。

例如。浮点比较有 3 种风格:

  • FCOM - 堆栈不变
  • FCOMP - ST(0) 弹出
  • FCOMPP - ST(0) 和 ST(1) 弹出

您还可以使用 FFREE 将堆栈寄存器显式设置为空(尽管我不记得曾经见过任何 FP 代码这样做)。

如果您愿意的话,您可以手动递增和递减 FP 堆栈指针,但这是我不记得使用过的另一个功能(这里有人吗?)。

曾经有一段时间,人们手动编写 FFT 内核以将三角递归关系保留在 x87 堆栈上,任何粗心的编码错误都会溢出堆栈。

此处值得注意的是,较新的 SIMD FP 指令比 x87 代码快得多,因此除非您这样做是为了练习,否则最好让编译器使用 HLL 中的 SSE2、AVX 或 AVX2 FP 代码。

© www.soinside.com 2019 - 2024. All rights reserved.