曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6644|回复: 2
打印 上一主题 下一主题

FPU 状态寄存器,控制寄存器,标记寄存器

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2010-2-27 23:05:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
状态寄存器

FPU 的状态寄存器表明 FPU 的操作情况,它包含在一个 16 为寄存器中,不同的位为不同的标志。
状态位
描述
0
非法操作异常标志
1
非格式化操作异常标志
2
除数为0异常标志
3
溢出异常标志
4
下溢异常标志
5
精度异常标志
6
堆栈错误
7
错误汇总状态
8
条件代码位0(C0)
9
条件代码位1(C1)
10
条件代码位2(C2)
11-13
堆栈顶部指针
14
条件代码位3(C3)
15
FPU繁忙标志

其中,8,9,10 和 14 为 4 个条件代码位,它们一起使用,表示浮点操作结果的特定错误代码。它们经常和异常标志一起使用,表示特定的异常情况。

FPU 的前 6 位 (0-5) 是异常标志。在处理过程中,当发生浮点异常时 FPU 设置它们。 FPU 保持它们的设置状态,直到程序运行时清空它们。当检测到堆栈溢出或者下溢(值对于 80 位堆栈寄存器过大或者过小)时,设置堆栈错误标志。

8 个寄存器中的任何一个都可以被指派为堆栈的顶端,每个后续的寄存器被相应的设为 ST(x) 寄存器。

使用 FSTSW 指令获得状态寄存器中的值(读到 AX 寄存器和一个双字节内存位置中):
.section .bss
    .lcomm status, 2
.section .text
.global _start
_start:
    nop
    fstsw %ax
    fstsw status

    movl $1, %eax
    movl $0, %ebx
    int $0x80
在 GDB 中调试看到:
(gdb) x/x &status
0x804908c <status>:    0x00000000

(gdb) print/x $eax
$1 = 0x0
上面看到,两个位置产生相同的值,说明在默认的情况下 FPU 状态寄存器的所有位都被设置位 0 。

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
沙发
 楼主| 发表于 2010-2-28 11:19:53 | 只看该作者

控制寄存器

控制寄存器

控制寄存器控制 FPU 内的浮点功能,使用一个 16 位寄存器,相应位的含义为:
控制位
描述
0
非法操作异常掩码
1
非格式化操作数异常掩码
2
除数位零异常掩码
3
溢出异常掩码
4
下溢异常掩码
5
精度异常掩码
6-7
保留
8-9
精度控制
10-11
舍入控制
12
无穷大控制
13-15
保留

前面 6 位用于控制使用状态寄存器中的哪些异常标志。当这些位中的一位被设置时,就会防止状态寄存器中对应的异常标志被设置。默认情况下,所有的掩码位都被设置,即屏蔽所有异常。

精度控制位可以设置 FPU 中用于数学计算的浮点精度,可以该白 FPU 计算浮点值花费的时间,这是非常有用的控制特性,精度控制设置如下:
      00 --- 单精度 (24位有效位)
      01 --- 未使用
      10 --- 双精度 (53位有效位)
      11 --- 扩展双精度 (64位有效位)
默认情况下,FPU 精度位扩展双精度,这是最为精确的值,但也是最为耗费时间。如果不打算使用这么高的精度,可以设置为单精度以加快浮点值的计算速度。

舍入控制位可以设置 FPU 如何舍入浮点计算的结果。舍入控制位的可能设置如下:
      00 --- 舍入到最近值
      01 --- 向下舍入 (向无穷大负值)
      10 --- 向上舍入 (向无穷大正值)
      11 --- 向零舍入
默认情况下,舍入控制位被设置为舍入到最近值。

控制寄存器的默认值是 0x037F 。可以使用 FSTCW 指令加载控制寄存器中的内容到内存中以查看其内容。也可以使用 FLDCW 指令改变设置,这条指令把内存中值加载到控制寄存器中。下面程序使用 FLDCW 指令把 FPU 的精度设置从扩展双精度改为单精度:
.section .data
newvalue:
    .byte 0x7f, 0x00

.section .text
    .lcomm control, 2

.section .text
.global _start
_start:
    nop
    fstcw    control
    fldcw    newvalue
    fstcw    control

    movl $1, %eax
    movl $0, %ebx
    int $0x80
通过调试器可以看到设置成功了:
12        fstcw    control
Current language:  auto
The current source language is "auto; currently asm".
(gdb) n
13        fldcw    newvalue
(gdb) x/x &control
0x804909c <control>:    0x0000037f
(gdb) n
14        fstcw    control
(gdb) n
16        movl $1, %eax
(gdb) x/x &control
0x804909c <control>:    0x0000007f

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
板凳
 楼主| 发表于 2010-3-2 00:28:34 | 只看该作者

标记寄存器

标记寄存器
标记寄存器用于标识 8 个 80 位 FPU 数据寄存器中的值。标记寄存器使用 16 位 (每个寄存器 2 位)标识每个 FPU 数据寄存器的内容。

每个标记值对应一个物理 FPU 寄存器。每个寄存器对应 2 位值,它们的不同组合有不同的含义,在任何给定时刻,FPU 数据寄存器可以包含下面内容:
      一个合法的扩展双精度值 (代码00)
      零值 (代码01)
      特殊的浮点值 (代码10)
      无内容 (空,代码 11)
通过检查标记寄存器可以快速确定 FPU 寄存器中是否包含合法数据,而不必读取和分析寄存器中的那内容。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-14 14:24 , Processed in 0.064505 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表