Board logo

标题: 理解 x87 FPU 的执行环境(3) [打印本页]

作者: yuyang911220    时间: 2016-10-19 20:24     标题: 理解 x87 FPU 的执行环境(3)

3. 浮点数据寄存器与 TOP 状态在 x86/x64 的机器的 x87 FPU 执行环境中有一组由 8 个 float pointer register(浮点寄存器)组成的 register stack

每个浮点寄存器 80-bit 宽,这些浮点寄存器存贮的格式被称作扩展双精度浮点格式
  • double extended-precision floating-point
扩展双精度浮点数是 80-bit 的,当 32 位的 single float point(单精度浮点数)和 64 位的 double float point(双精度浮点数)被装载到浮点寄存器时,会被自动转换为 80 位的扩展双精度浮点数。
这些浮点寄存器组成一个寄存器栈,x87 FPU 以 stack 结构的形式使用这些物理的浮点寄存器,由 status word 寄存器中的 TOP 部分指出这个寄存器栈当前的 stack top(栈顶)。
3.1 stack registers由 8 个 物理的浮点数据寄存器组成的 stack,每个物理浮点数据寄存器对应一个 stack register,从 st(0) - st(7),栈顶是 st(0) 寄存器,这些 stack register 的虚拟的,它们实际上只是 st(0) 的偏移值,st(0) 具体对应哪个物理浮点寄存器由 status word 中的 TOP 部分决定。

在上图这个 16 位的 status word 寄存器中,我们关注其中的 Bit13 - Bit11 TOP(top of stack pointer)它的取值范围是:
TOP 值指示一个物理的浮点寄存器,TOP 的值给出当前的栈顶,每入栈一次,TOP 的值减 1,以下面为例
下面是关于 stack register 的使用,在 Intel manual 上的例子:
a = 5.6
b = 2.4
c = 3.8
d = 10.3
式子:(a * b) + (c * d) = (5.6 * 2.4) + (3.8 * 10.3) = ?
下面的 x87 指令序列用来完成这项任务:
fld a                      ; st(0) = a
fmul b                     ; st(0) = st(0) * b
fld c                      ; st(0) = c, st(1) = a * b
fmul d                     ; st(0) = st(0) * d
fadd st(1)                 ; st(0) = st(0) + st(1)
假设在这段代码执行之前,当前的 TOP = 3,也就是说 st(0) = fpr3, st(1) = fpr4 那么:
TOP - 1 此时 TOP = 2 指示 st(0) 将是 fpr2 寄存器,将 a 压入 stack 中, 那么结果是 fpr2 寄存器的值是 5.6
指令将栈顶 st(0) = st(0) * 2.4 = 5.6 * 2.4 = 13.44 此时 fpr2 寄存器的值是 13.44 栈顶依然是 fpr2 寄存器
TOP - 1 此时 TOP = 1 指示 st(0) 将是 fpr1 寄存器,将 c 压入 stack 中,结果 fpr1 寄存器的值是 3.8,在这里 st(0) = fpr1st(1) = fpr2,fpr2 寄存器已经不是栈顶了。
结果是 st(0) = st(0) * 10.3 = 39.14,栈顶的值是 39.14
指令执行 st(0) = st(0) + st(1),结果是 fpr1 + fpr2 = 13.44 + 39.14 = 52.58
3.2 TOP 的回卷当 TOP = 0 时,也就是说 st(0) 在 fpr0 寄存器上,就是遭遇到回卷的问题:
当再执行入栈操作后,结果为:
每个 stack register 相应地减 1 向下移一位,st(0) 则回卷至 fpr7

4. x87 Environment 初始化状态现在我们来看看 processor 在加电初始化的 x87 environment:
control word 为 0040 表明所有的 exception mask 为 0,不接受这些异常,精度控制不可用,TOP 初始状态为 0,指向 fpr0,所有的 stack register 都是无效的。
经过 finit/fninit 指令初始化后,x87 environment 状态为:
finit/fninit 后的所有 stack registers 状态为空,是可用状态,接受所有的 x87 异常。





欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0