12

我最近在 FPU 堆栈溢出方面遇到了一些麻烦。我设法将其追溯到一个有缺陷的库函数,该函数每次调用时都会将垃圾值推送到 FPU 堆栈上,并且从不清理它。

幸运的是,这很容易重现,我确切地知道是什么条件造成的。我可以将一个内联 ASM 块放入调用该例程的例程中,以将顶部值从 FPU 堆栈中弹出……除非我不太清楚该写什么。我的 ASM-fu 还算中规中矩,但没那么强。

那么,假设它是垃圾数据并且我不关心该值,那么在 x86 程序集中摆脱 FPU 堆栈上的最高值的最简单方法是什么?

4

4 回答 4

13

对于 Delphi/BASM,在我看来,一次弹出 FPU 堆栈的最简单方法是:

asm
 fstp st(0)
end;
于 2011-01-26T21:53:20.943 回答
9

如果您知道需要将堆栈调整多少,您可以使用fincstp. 您还想要ffree递增的寄存器。

但是,可能最简单的解决方案是使用弹出数据传输操作之一,例如fstp. 通常,您会将结果存储到内存区域以供以后使用,例如:

mem_area: defs 10         ; ten bytes for 80 bits
          fstp mem_area   ; pop it

但是,如果您知道您只想丢弃该值,则可以将st(0)其自身用作目标,从而节省内存需求:

fstp st(0)

有关说明的详细指南(尤其是此位) ,请参见此处。

于 2011-01-23T05:11:33.477 回答
4

如果st0是唯一正在使用的 x87 寄存器,您可以使用以下命令清空它:

ffree st0

但是,如果有多个堆栈寄存器在使用中,这与普通弹出不同,因为它不会调整栈顶指针(x87 状态字中的 TOP 字段)。

请参阅Simply FPU x87 教程的寄存器章节

st1仍然会st1在释放st0而不是弹出之后,所以这通常不是你想要的,并且与fstp st0.

于 2011-01-23T13:36:57.267 回答
2

只需使用弹出的任何(快速)指令将其从堆栈中弹出。 8087指令集

如果这不起作用,FUCOMPP 会弹出两次。

于 2011-01-23T05:30:33.130 回答