计算机的算术运算


溢出发生的条件:

  • 加法:
    • 同正得负
    • 同负得正
  • 减法:
    • 正负得负
    • 负正得正

对于 MiPS 指令而言:

  • 有符号数的加减法(add、sub、addi)在溢出时产生异常
  • 无符号数的加减法(addu、subu、addiu)在溢出时不产生异常

addiu 在做无符号数的加法时,立即数符号扩展至32位

MIPS 使用异常程序计数器 $EPC$ 来保存导致异常的指令地址,指令 $mcf0$ 用来将 $EPC$ 存入一个通用寄存器

饱和操作是指结果发生溢出时,结果被设置为最大的正数或者最小的负数,一般用于多媒体操作

检测 MIPS 溢出举例:

  1. 对于有符号加法检测的步骤为:

    1. 首先判断加数和被加数的符号是否相异,如果相异则不会溢出,否则进行下一步检验
    2. 判断相加之后的结果于原来加数的符号是否相同
    • 代码如下:喵喵喵
  2. 对于无符号加法的检测步骤为:

    1. 判断两数之和是否超过 $2^{31}-1$ ,方法为将其中一个加数取反看是否小于另一个加数
    2. 代码如下:喵喵喵

MIPS 提供了寄存器 $Hi$ 和 $Lo$ 来容纳乘法过程中 64 位的乘积,例如:

  • $mult/multu \quad rs,\; rt$ 将寄存器 $rs$ 和 $rt$ 的数据相乘,乘积的低32位存入$Lo$ ,高32位存入 $Hi$
  • 指令 $mul \quad rd,\; rs,\; rt$ 将 $rs$ 和 $rt$ 乘积的低32位存入寄存器 $rd$ 中
  • 指令 $mfhi/mflo \quad rd$ 将 $Hi/Lo$ 的值送入寄存器 $rd$

MIPS 乘法指令都忽略溢出,需要有如软件来检测是否可能因为积过大而32位不够表示,对于 multu 指令,可以检测 Hi 的值是否为0,对于mult 指令,可以检测 Hi 的值是否为 Lo 的符号为

在有符号的除法中,必须满足等式 $被除数=商 \times 除数 + 余数$ 以及 $-(x \div y)=(-x)\div y$,因此余数的正负号的设置必须格外小心,例如:

  • $-7 \div 2=-3…-1$ 而不是 $-7 \div 2 = -4…1$ (不满足后面一条性质)

提供了 $Hi$ 和 $Lo$ 来存储余数和商:

  • $div \quad rs,\; rt$ 将 $rs \div rt$ 的商存入寄存器 $Lo$,余数存入寄存器 $Hi$
  • $divu$ 无符号的除法

MIPS 除法指令同样忽略溢出,需要软件来检测商是否溢出

P130精解不理解

检测溢出可以用最高为的进位和次高为的进位相异或,$1 \Rightarrow Overflow \quad else \; no \; overflow$

规格化数:没有前导零且小数点左边只有一位整数(如 $1.0*10^{-9}$)

MIPS 中浮点数的表示:1位符号位+8位指数位+23位尾数位(指数部分表示数的范围,尾数部分表示数的精度),MIPS 中浮点数的值可用 $(-1)^S \times (1+F) \times 2^E$ 其中 $F$ 为尾数,$E$ 为指数

浮点数的溢出:

  • 上溢:正的指数太大而导致指数域放不下的情况
  • 下溢:负的指数太小而导致指数域放不下的情况

浮点数的精度:

  • 单精度:浮点数由一个32位的字表示(1+8+23),范围约为 $2.0 \times 10^{\pm38}$
  • 双精度:浮点数由两个32位的字表示(1+11+52),范围约为 $2.0 \times 10^{\pm308}$

为了提高精度,$IEEE \quad 754$ 通常省略了前导一,即将浮点数的表示为:$(-1)^S \times (1+F) \times 2^E$ ,$F \in [0,1)$

如果从左到右标记尾数依次为 $s1, s2, s3, … ,s_t$ ,且指数的值为 $E$ ,则浮点数的值为:$(-1)^S \times [1+s_1 \times 2^{-1}+s_2 \times 2^{-2}+…] \times 2^E$

喵喵喵

带偏阶的计数法:

  • 希望计数法能将最小的负数表示为 $000…00_2$ ,最大的正数表示为 $1111…11_2$ ,我们通常在原数的基础上加上一个偏阶
  • $IEEE \quad 754$ 规定单精度的偏阶为 127,例如指数为-1时,会表示成126,即 $01111110_2$ ,指数为+1时,会表示成 128,即 $10000000_2$ ;双精度额偏阶规定为 1023,给指数带偏阶之后,浮点数的表示为: $(-1)^S \times (1+F) \times 2^{E-Bias}$

求 $-0.75_{10}$ 的单精度和双精度表示:

  • 单精度:{1, 01111110, 100…0}
  • 双精度:{1, 011111111110, 100…0}

浮点数加法的步骤:

  1. 将指数较小的数向指数较大的数对齐
  2. 将有效数相加
  3. 规格化(不一定要做)
  4. 四舍五入(不一定要做,做了之后由于进位可能会返回步骤3)
  • 例子1(假定有效位数为4): $9.999 \times 10^{1}+1.610 \times 10^{-1}$
    1. $1.610 \times 10^{-1} \rightarrow 0.016 \times 10^1$
    2. $9.999 \times 10^1+0.016 \times 10^1=10.0015\times10^1$
    3. $10.0015 \times 10^1=1.0015 \times10^2$
    4. $1.0015 \times 10^2 \rightarrow 1.002 \times 10^2$
  • 例子2(假定有效位数为4):$0.5_{10}+(-0.4375_{10})$
    1. 两者的科学表示分别为 $1.000 \times 2^{-1}、-1.110\times2^{-2}$
    2. $-1.110 \times 2^{-2} \rightarrow -0.111 \times2^{-1}$
    3. $1.000 \times 2^{-1} + -0.111 \times 2^{-1}=0.001\times2^{-1}$
    4. $0.001\times2^{-1} \rightarrow 1.000 \times 2^{-4}$
  • 浮点数基本结构示意图:喵喵喵

浮点数乘法的步骤:

  1. 将源操作数的指数相加作为积的指数(注意要减去一个偏阶)
  2. 计算有效数的乘法
  3. 规格化(检查上溢或者下溢)
  4. 舍入
  5. 积的符号相同为正,相异为负
  • 例子1(假定有效位为4):计算 $0.5_{10} \times (-0.4375)_{10}$
    1. 二进制表示分别为:$1.000\times2^{-1}$ 和 $-1.110 \times 2^{-2}$
    2. 计算积的偏阶为:$-1+(-2)=-3$ (此时是没有带偏阶的,所以不需要减去偏阶)
    3. 将有效数相乘:$1.000 \times 1.110=1.110$,因此此时得到的结果为 $1.110 \times 2^{-3}$
    4. 符合规格化且没有发生溢出
    5. 舍入后结果不变
    6. 符号为 $-$

MIPS 中的浮点数指令:

  • MIPS 常见的浮点数指令为:喵喵喵
  • MIPS 中有32个32位浮点寄存器$(\$f_0,\$f_1,…,\$f_{31})$ ,单精度浮点数直接用某一个寄存器来表示,双精度浮点数由一组单精度寄存器(偶数+奇数)来表示,例如 $\$f_2,\$f_3$ 形成一个双精度寄存器,称为 $\$f_2$
  • 常见的浮点数指令如图:喵喵喵
喵喵喵

浮点算数的精确性:

  • 保护位:右边多保留的第一位
  • 舍入位:右边多保留的第二位
  • 粘贴位:当舍入位右边有非零的数即置1,主要用于当保护位和舍入位恰好是10的情况

混合乘加指令执行一次乘法和一次加法,但只在加法后执行一次舍入,能够提高浮点性能

注意:

  • 为了从一次浮点操作中最大限度的获得精度,标准允许一些数(指数最小时)以非规格化的形式出现,例如:
    • 最小的正的单精度规格化数为:$1.00…0 \times 2^{-126}$
    • 最小的正的单精度非规格化数为:$0.000…1\times2^{-126}$
  • 左移指令可以代替2的幂次方数相乘,右移指令不能代替2的幂次方数相除(对于无符号整数是对的,但是对于有符号整数不一定正确(负数可能变成正数))
  • 浮点数加法没有结合律(例如$c=-1.5 \times 10^{38},a=1.5\times10^{38},b=1.0$,则$c+(a+b)=0$ 而 $(c+a)+b=1$)

文章作者: qiufeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 qiufeng !
评论
 上一篇
处理器 处理器
逻辑单元: 组合单元:处理数据值的单元,其输出只取决于当前的输入。例如:alu、门 状态单元:存储状态的单元。例如:指令存储器、数据存储器、寄存器。一个状态单元至少有两个输入(时钟信号和写入单元的值)和一个输出 时钟方法:规定了信号可以读
下一篇 
计算机的语言 计算机的语言
常用的寄存器(32个): $\$0(\$zero)$:零寄存器,值恒为 $0$ $\$1(\$at)$:寄存器 $at$ ,保留给汇编器使用 $\$2、\$3(\$v_0、\$v_1)$:函数返回值寄存器,调用时不保存 $\$4-\$7(
2020-04-12 qiufeng
  目录