7

我正在尝试将 80 位扩展精度浮点数(在缓冲区中)转换为双精度。缓冲区基本上包含 x87 寄存器的内容。

这个问题帮助我入门,因为我对 IEEE 标准并不十分熟悉。无论如何,我正在努力寻找有关 80 位格式的次规范(或非规范化)数字的有用信息。我所知道的是,与 float32 或 float64 不同,它在尾数中没有隐藏位(没有隐含添加 1.0),因此了解数字是否标准化的一种方法是检查尾数中的最高位是否已设置. 这给我留下了以下问题:

根据维基百科告诉我的内容,float32 和 float64 表示一个(有偏的)指数为 0 且尾数非零的次正规数。

  • 这在 80 位浮点数中告诉我什么?
  • 尾数 < 1.0 的 80 位浮点数甚至可以有非零指数吗?
  • 或者,指数为 0 的 80 位浮点数甚至可以有尾数 >= 1.0 吗?

编辑:我想问题归结为:

我可以期望 FPU 清理 x87 寄存器中的指数和最高尾数位吗?

如果不是,转换结果应该是什么数字?在那种情况下我应该完全忽略指数吗?还是qNaN?

编辑:

我阅读了英特尔手册(英特尔® 64 和 IA-32 架构软件开发人员手册,第 1 卷:基本架构)中的 FPU 部分,这没有我担心的那么可怕。事实证明,未定义以下值:

  • 指数 == 0 + 设置了最高位的尾数
  • 指数 != 0 + 尾数没有最高位设置

它没有提到这些值是否可以在野外出现,也没有提到它们是否在内部转换。所以我实际上掸掉了 Ollydbg 并手动设置了 x87 寄存器中的位。我制作了 ST(0) 以包含指数中设置的所有位和尾数 0。然后我让它执行

FSTP QWORD [ESP]
FLD QWORD [ESP]

存储的值[ESP]被转换为信号 NaN。之后FLDST(0)包含一个安静的 NaN。

我想这回答了我的问题。我接受了J-16 SDiZ的解决方案,因为它是最直接的解决方案(尽管它没有明确解释一些更精细的细节)。

总之,案子解决了。谢谢大家。

4

2 回答 2

3

查找低于正常 80 位数信息的问题可能是因为 8087 没有对它们使用任何特殊的非规范化。在Type float (C)的 MSDN 页面上找到了这个:

此表中列出的值仅适用于标准化浮点数;非规格化浮点数具有较小的最小值。请注意,保留在 80x87 寄存器中的数字始终以 80 位规范化形式表示;当存储在 32 位或 64 位浮点变量(float 类型和 long 类型的变量)中时,数字只能以非规范化形式表示。

编辑

以上对于 Microsoft 如何使用 FPU 寄存器可能是正确的。找到另一个表明这一点的来源:

FPU 数据类型

80x87 FPU 通常以标准化格式存储值。当浮点数归一化时,HO 位始终为 1。在 32 位和 64 位浮点格式中,80x87 实际上并不存储该位,80x87 始终假定它为 1。因此,32 位和 64 位浮点数总是被标准化。在扩展精度 80 位浮点格式中,80x87 不假设尾数的 HO 位为 1,数字的 HO 位作为位串的一部分出现。

归一化值提供给定位数的最大精度。但是,我们可以用 80 位格式表示大量的非归一化值。这些值非常接近于零,代表尾数 HO 位不为零的一组值。80x87 FPU 支持一种特殊形式的 80 位,称为非规范化值。

于 2011-08-06T14:30:04.703 回答
3

试试SoftFloat库,它有floatx80_to_float32, floatx80_to_float64floatx80_to_float128. 检测原生格式,采取相应措施。

于 2011-08-06T16:28:25.277 回答