非规格化数(Denormals)是一种用于表示非常小数值的特殊类值。它可以表示渐进下溢或渐进精度丢失情况。通常要求数值表示成规格化数(左移直到有效数的最高有效位是位1)。然而非规格化数的有效数最高有效位不是1。此时偏置型指数0x00...00分别是值为2-126、2-1022、2-16382的短实数、长实数和临时实数指数值的特殊表示方式。这种表示比较特殊,因为偏置型指数0x00...01对三种实数类型也分别表示相同的指数值2-126、2-1022、2-16382。

伪非规格化类数值(Pseudo-denormals)是有效数最高有效位为1的值,而非规格化类数值的该位是0。伪非规格化数很少见,它们可以用规格化类数来表示却没有这么做。因为上面已经说明特殊的偏置指数0x00...00与规格化数的指数0x00...01具有相同的值。因此伪非规格化类数可以表示成规格化类数值。

另一种特殊情况是NaN。NaN是指“不是一个数”(Not a Number)。NaN有两种形式:会产生信号(Signaling)的和不会产生信号的或称为安静的(Quiet)。当一个产生信号的NaN(SNaN)被用于操作时就会引发一个无效操作异常,而一个安静的NaN(QNaN)则不会。SnaN是一类会引发无效操作异常的数值。使用的方法就是程序先把变量都初始化为SNaN值,在实际使用这个变量时还需要对其进行真正的赋值。这样若操作过程中使用了一个未被初始化的值就会引发异常。当然,NaN类数值也可以用来存储其他信息。

80387自身不会产生SNaN类的值,但会产生QNaN类的值。当发生无效操作异常时80387就会产生一个QNaN类值,并且操作的结果将是不确定值(Indefinite)。不确定值是一种特殊的QNaN类值。每种数据类型都有一个表示不确定值的数。对于整型数则是用其最大负数来表示其不确定值。

另外还有一些80387不支持的临时实数值,即那些没有在上表中列出的数值范围。若80387遇到这些数值,就会引发无效操作异常。

11.1.2 数学协处理器功能和结构

80386虽然是一个通用微处理器,但其指令并不是非常适用于数学计算。因此若使用80386来执行数学计算,那么就需要编制非常复杂的程序,而且执行效率也相对较低。80387作为80386的辅助处理芯片,极大地扩展了程序员的编程范围。以前程序员不太可能做到的事,使用协处理器后就可以很容易地,并且快速而精确地完成。

80387具有一组特别的寄存器。这组寄存器可以让80387直接操作比80386所能处理的大或小几个数量级的数值。80386使用2进制补数方式表示一个数。这种方法不适合用来表示小数。而80387并不使用2的补数方法来表示数值,它使用了IEEE标准754规定的80位(10个字节)格式。这种格式不仅具有广泛的兼容性,而且能够使用二进制表示极大(或极小)的数值。例如,它能表示大到1.21×104932数值,也能处理小到3.3×10-4932的数。80387并不保持固定小数点的位置,如果数值小的话就多使用一些小数位,如果数值大的话就少用几位小数位。因此小数点的位置是可以“浮动”的。这也是术语“浮点”数的由来。

为支持浮点运算,80387中包含三组寄存器,如图11-5所示。① 8个80位长的数据寄存器(累加器),可用于临时存放8个浮点操作数,并且这些累加器可以执行栈式操作;② 3个16位状态和控制寄存器:一个状态字寄存器SWD、一个控制字寄存器CWD和一个特征(TAG)寄存器;③ 4个32位出错指针寄存器(FIP、FCS、FOO和FOS)用于确定导致80387内部异常的指令和内存操作数。

Linux内核完全剖析---数学协处理器1)



相关内容