曲径通幽论坛

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

部分余数

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2010-3-14 13:50:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
部分余数的概念与如何执行浮点除法有关。除法操作的余数由被除数对除数的一系列减法决定。在每次减法迭代时,中间余数称为部分余数(Partial remainder)。当部分余数小于除数时( 不能再执行减法操作,否则就会产生负数 ),迭代停止。在除法操作结束时,最终的答案是代表减法迭代次数的整数值(商(quotient)),以及表示最终的部分余数的浮点值(余数(remainder))。

根据执行除法需要多少次迭代,可能有很多部分余数。迭代的次数取决于被除数和除数的指数值之间的差值。每次减法不能使被除数的指数值的减少量超过 63 ( 双精度的指数范围 )。

确定除法余数的基本方法是确定被除数和除数的除法的浮点商,然后把这个值舍入到最近的整数。那么,余数就是除数和商相乘的结果与被除数之间的差值。例如,为了计算 20.65 除以 3.97 的余数,可以执行如下步骤:
1) 20.65/3.97=5.201511335
2) 5*3.97=19.85
3) 20.65-19.85=0.8
计算浮点除法余数有两个指令: FPREM 和 FPREM1 ,它们的工作方法稍有区别。

在创建任何标准之前,Intel 就开发了 FPREM 指令,它使用默认的 FPU 向零舍入的方法,用于计算整数商值,然后确定余数。

但是,在 IEEE 创建标准时,它选择在计算余数之前,使商值向上舍入到最近的整数值

虽然两者看起来只有细微的区别,但是在处理过程中对计算部分余数会造成很大的影响。出于这个原因,Intel 不但保持了 FPREM 指令的原始形式,而且另外创建了 FPREM1 指令,后者使用 IEEE 方法计算部分余数。

计算部分余数的问题在于必须知道迭代过程在什么时候完成。FPREM 和 FPREM1 指令都使用 FPU 状态寄存器的条件代码 2 (状态寄存器的第 10 位)表示迭代何时完成。当需要更多的迭代时,就设置 C2 位,当迭代完成时,就清空 C2 位。

位了检查 C2 位,必须首先使用 FSTSW 指令把状态寄存器的内容复制到内存位置或者 AX 寄存器中,然后使用 TEST 指令判断这一位是否设置了。

下面程序使用 FPREM1 指令执行简单的浮点除法:
.section .data
value1:
    .float 20.65
value2:
    .float 3.97

.section .bss
    .lcomm result, 4

.section .text
.global _start

_start:
    nop
    finit
    flds value2
    flds value1

loop:
    fprem1
    fstsw %ax
    testb $4, %ah
    jnz loop
   
    fsts result
    movl $1, %eax
    movl $0, %ebx
    int $0x80
说明:
注意,FPREM1 是一个迭代的处理过程,它可能不是一步到位的,也就是不能保证它经过第一次执行就能得到最终的答案。所以,必须使用 TEST 指令检查 C2 条件位的值 (先使用 FSTSW 指令把它送到 AX 寄存器)。如果这一位被设置了,那么 TEST 指令就会产生非 0 值,这样 JNZ 会继续返回 loop 进行下一个迭代。反之,如果这一位被清零了,那么 JNZ 就不会跳转,而是顺序执行下去。余数值存储在 ST0 寄存器中,程序中还将余数保存到 result 内存处。

在 GDB 中可以看到余数值:
(gdb) x/f &result
0x80490a8 <result>:    0.799999475

虽然余数存储在 ST0 寄存器中,但实际的商没有存储在寄存器中。商值的最后 3 个有效位存储在状态寄存器中,使用状态寄存器中剩余的条件码位,如下:
      商位 0 在条件位 1
      商位 1 在条件位 3
      商位 2 在条件位 0
必须手动地提取这些位以便构成商值的最低 3 位。

现在跟踪一下这个商:
在 fprem1 这里下断,然后运行至此,执行 fprem1 之前,先看一下状态寄存器内容:
fstat          0x3000    12288
发现C0, C1, C2, C3都为0。
现在执行 fprem1 指令,然后再看一下相关条件位:
fstat          0x3300    13056
我们不关心 C2,就看一下 C3, C1, C0的值,分别为 0, 1, 1 。按照上面所说的商的位置,组合起来为: 101 ,即为 5。所以,商为 5 。

这里,只能提取商的低 3 位,超出了不能从此获得商的值。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-5-14 06:23 , Processed in 0.074936 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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