我正在尝试将80位扩展精度浮点数(在缓冲区中)转换为double。 缓冲区基本上包含x87寄存器的内容。
This question帮助我开始,因为我并不熟悉IEEE标准。 无论如何,我正在努力寻找有关80位格式的次正规(或非规范化)数字的有用信息。 我所知道的是,与float32或float64不同,它在尾数中没有隐藏位(没有隐含的1.0加法),所以知道数字是否规范化的一种方法是检查尾数中的最高位是否设置。这让我有了以下问题:
维基百科告诉我,float32和float64表示一个次正规数,(偏差)指数为0,尾数为非零。
我能指望FPU清理x87寄存器中的指数和最高尾数位吗?
如果没有,转换结果应该是什么类型的数字?在这种情况下,我应该完全忽略指数吗?还是qNaN?
修改
我阅读了英特尔手册(英特尔®64和IA-32架构软件开发人员手册,第1卷:基础架构)中的FPU部分,这一点并不像我担心的那么可怕。事实证明,未定义以下值:
没有提到这些值是否可以在野外出现,也不会在内部转换。 所以我实际上除了Ollydbg并手动设置x87寄存器中的位。 我制作了ST(0)来包含指数中设置的所有位和尾数为0.然后我让它执行
FSTP QWORD [ESP]
FLD QWORD [ESP]
存储在[ESP]
的值被转换为信令NaN。
在FLD
之后,ST(0)
包含一个安静的NaN。
我猜这回答了我的问题。我接受了 J-16 SDiZ 的解决方案,因为它是最直接的解决方案(尽管它没有明确解释一些更精细的细节)。
无论如何,案件已经解决了。谢谢,大家。
答案 0 :(得分:3)
查找关于子正常80位数的信息的问题可能是因为8087没有对它们使用任何特殊的非规范化。在Type float (C)上的MSDN页面上找到了这个:
此表中列出的值仅适用于规范化 浮点数字;非规范化的浮点数有一个 最小值较小。 请注意,数字保留在80x87寄存器中 始终以80位标准化形式表示; 数字只能是 以32位或64位存储时以非规范化形式表示 浮点变量(float和long类型的变量)。
修改强>
以上可能适用于Microsoft如何使用FPU寄存器。找到了另一个表明这一点的来源:
80x87 FPU通常以标准化格式存储值。当一个 浮点数被归一化,H.O。位总是一个。在 32位和64位浮点格式,实际上并不是80x87 存储这个位,80x87总是假定它是一个。因此,32 并且64位浮点数始终被标准化。 在 扩展精度80位浮点格式,80x87没有 假设H.O.尾数的位是一个,H.O。一点点 数字显示为位串的一部分。
标准化值为给定数量的值提供最大精度 位。但是,存在大量非标准化值 我们可以用80位格式表示。 这些值非常接近 为零并表示其尾数为H.O.的值的集合。有点不对 零。 80x87 FPU支持80位的特殊形式 非规范化值。
答案 1 :(得分:3)
试用SoftFloat库,它有floatx80_to_float32
,floatx80_to_float64
和floatx80_to_float128
。检测原生格式,采取相应行动。