hai*_* ha 2 floating-point x86 assembly x87
以下是使用FLD时可能出现的异常:
#IS发生堆栈下溢或溢出。
#IA源操作数是 SNaN。如果源操作数是双扩展精度浮点格式(FLD m80fp 或 FLD ST(i)),则不会发生。
#D源操作数是一个非正规值。如果源操作数是双扩展精度浮点格式,则不会发生。
为什么 #IA 异常“如果源操作数是双扩展精度浮点格式,则不会发生”?
我认为双精度浮点和双扩展精度浮点格式基本相同。两者都能够编码 SNaN。
这种差异是否有任何合乎逻辑的原因,或者只是它的方式?
fld m64fp并且m32fp必须转换为 x87 寄存器中使用的内部 80 位格式。您可以将其视为可以引发#SNaN 异常的转换过程。
fld m80fp只是已经采用本机内部格式的纯数据负载,例如frstor.
(请注意,AMD64 CPU确实会在 SNaN 80 位负载上发出 FP 异常信号;这是AMD 和 Intel实现的 x86-64之间的细微差别之一)。
从浮点数或双精度数到扩展 80 位的转换必须检查源浮点数的位,扩展尾数并根据指数字段为非零(正常或次正常)添加显式前导 1 或 0。
这个显式与隐式尾数位是x87 双扩展与 IEEE binary64 aka double 或 qword之间的主要区别。两者都可以编码 SNaN,但它们绝对不像 binary32 和 binary64 那样“基本相同”(只是更宽的字段)。
这种“不一致”大概可以追溯到 8087,当时晶体管预算非常有限。fld m80fp即使不使用通常的转换硬件,检查 SNaN 也会花费额外的晶体管。
请注意,这fld m80fp是使 x87 FPU 读取FP 值的唯一方法tbyte(除了frstor更现代的fxrstor或xrstor)。没有fadd m80fp或任何东西。因此,任何涉及从内存读取 m80fp 的操作都不必引发 SNaN 异常。
大多数 FP 数学指令都有内存源操作数形式,例如fadd st0, m64fp和fadd st0, m32fp,它们大概也需要转换为内部格式作为其操作的一部分。因此,您希望检测内存源 SNaN 作为该转换的一部分是有道理的。
因此,如果您正在设计 8087,那么在转换 32 位和 64 位输入时让处理从内存中加载的逻辑检查 SNaN 是有意义的,而不是在仅加载 80 位本机格式时。这可能是 Intel 最初继承该行为的地方,并且使后来的 CPU 变得不同是没有意义的,因此他们保留了这种行为。
IDK 是将其视为不利因素,还是认为您可以加载 80 位本机 FP 值而不会引发异常的想法实际上是一个好主意。AMD 显然决定不这样做,并且确实发出了fld m80fpSNaN的 FP 异常信号。
或者,您可以将其视为一件坏事,fld dword / qword当仅重新格式化浮点数而不会丢失数据且不进行任何实际计算时,可能会引发异常。
背景:
通常,您一开始就不会遇到 SNaN。除以 0 等无效操作的输出是 QNaN、IIRC。因此,如果您自己使用整数指令或作为静态常量数据创建一个,您只会得到 SNaN。(我认为。)
当然,通常您会屏蔽 FP 异常,因此它不会出错,只需在 FP 状态字中设置一个粘滞位即可。