计算机组成原理复习(2)

考研复习第 3,4 天

计算机组成原理相关内容的复习

  • 原码,补码,反码,移码
  • 移位,加减法,乘法运算

数据编码

原码,补码,反码,移码

原码

字面意思,有符号时,最高位表示负号

补码

最高位权值为负,其它与原码一致。

反码

在原码的基础上,若最高位为1,则对原码除符号位所有位取反

移码

看成无符号然后-一个偏置值即可。

单符号与双符号

单符号一般写的时候用小数点隔开,但是不表示小数点的含义,比如 0.0001 如果是原码表示正数的1,1.0001 如果是原码表示负数的1。在此基础上,还可以再做一个符号的扩展,用于判断溢出。若出现 01,则表示正溢,若出现 10,则表示负溢。

比如 00.1111 如果表示原码就是正数的15,11.1111 如果表示原码就是负数的15,而 10.0001 不能表示一个正确的数,因为它溢出了,同样 01.0001 也不行。但是在下面的乘法算法的时候,允许临时溢出。

移位运算

主要是循环移位有一个带进位和不带进位的区别。带进位就是说,在挪出去的过程中要算上 CF 一起,如果不带进位,那么原本被丢弃的位进入 CF 和最高位或者最低位。

乘法和除法

有这么几种算法,学一下吧~

原码一位乘法

总结来说就是:被乘数和乘数均取绝对值参加运算,符号位不参与运算单独考虑~

然后自己也豁然开朗了,假设两数为n+1位(带符号)遵循这么个步骤:

  1. 取符号,结果的符号为俩符号的异或。
  2. z 取 |y| 为当前结果,扩展 n+1 位。
  3. 每次取得 z 的最低位的值,如果为 1,那么高 n 位整体加上 |x|,否则加上0,加完之后,逻辑右移一位。
  4. 重复(步骤3) n次。

举个例子,拿两个八位有符号整数的原码。

x=0.10010101

y=0.11010110

首先符号都是正的没问题,然后设定一个 z,值跟|y|一样,然后扩展 8+1 位,这里我扩展到了点之前,这个点不是小数点。

  1. z=00.0000000011010110|
  2. 取出z的最低位 为 0,给z的高八位加上0,然后逻辑右移,z=00.0000000001101011|0
  3. 取出z的最低位 为 1,给z的高八位加上|x|,然后逻辑右移,z=00.0100101010110101|10
  4. 取出z的最低位 为 1,给z的高八位加上|x|,然后逻辑右移,z=00.0110111111011010|110
  5. 取出z的最低位 为 0,给z的高八位加上0,然后逻辑右移,z=00.0011011111101101|0110
  6. 取出z的最低位 为 1,给z的高八位加上|x|,然后逻辑右移,z=00.0110011001110110|10110
  7. 取出z的最低位 为 0,给z的高八位加上0,然后逻辑右移,z=00.0011001100111011|010110
  8. 取出z的最低位 为 1,给z的高八位加上|x|,然后逻辑右移,z=00.0110010000011101|1010110
  9. 取出z的最低位 为 1,给z的高八位加上|x|,然后逻辑右移,z=00.01111100100011100|11010110
  10. 结束,z 最后就是最后的结果,再加上符号即可。

这里需要注意,为什么需要扩展 N+1 位,因为临时乘,然后加,最高位可能产生进位,如果不保留那么移位之后,高位必为0,显然是不合理的。

最后算结果的时候,因为还要加符号,所以直到最后出结果也是需要 2N+1位的。

补码一位乘法(BOOTH算法)

总结来说就是:所有位均参与运算

假设x,y的位数为n+1(有符号)位。

  1. 取z为y的值,末位加一个辅助位。
  2. 取最低位+辅助位的组合,若组合为00或11,则直接右移一位,若组合为01,则加x的补码,10则加-x的补码,也就是~x+1 加完之后都要算数右移一位。
  3. 重复(步骤2) n+1次。

比如x = -0.1101,y=0.1011

分别写出它们的补码:[x]补=11.0011,[y]补=00.1011,[-x]补=00.1101。

先取 y 的值作为 z 的值,并进行扩展(这里可能是符号扩展)z=00.00001011|0(辅助位)|

取出最低位和辅助位的组合,结果为 10,那么加上 -x 的补码,再右移一位,z=00.01101101|1|0

取出最低位和辅助位的组合,结果为 11,那么加上 0,再右移一位,z=00.00110110|1|10

取出最低位和辅助位的组合,结果为 01,那么加上 x 的补码,再右移一位,z=11.10110011|0|110

取出最低位和辅助位的组合,结果为 10,那么加上 -x 的补码,再右移一位,z=00.01000001|1|0110

最后一个步骤比较特殊,它要看当前 y 补码的符号位和辅助位的组合:那么得到了 01,就是加上 x 的补码并且不会右移了,最后得到 z=11.01110001。

再比如,最简单的x=-0.0001 y=-0.0001

不过这里不能和之前一样了,跟之前的有点出入,但是按照上面那个思路是能得到正确结果的,只是不连通,介绍一个连通的思路:

  1. 取z=0,y补码末尾添0。
  2. 从低位开始,扫补码的低两位,每次左移一位。
  3. 若组合为00或11,则直接右移一位,若组合为01,则加x的补码,10则加-x的补码,也就是~x+1 加完之后都要算数右移一位。
  4. 重复(步骤2)n+1 次。

模拟一遍:

  1. z=00.0000,[x]补=[y]补=11.1111,[-x]补=00.0001,然后把 y 变成这种形式:1.111[10]。
  2. 取得10,加上[-x]补,再算数右移一位,得到00.00001,同时y也移动:1.11[11]0。
  3. 取得11,加0,算数右移一位,得到00.000001,同时y也移动:1.1[11]10。
  4. 取得11,加0,算数右移一位,得到00.0000001,同时y也移动:1.[11]110。
  5. 取得11,加0,算数右移一位,得到00.00000001,同时y也移动:[1.1]1110。
  6. 取得11,加0,结束。最后得到00.00000001,显然就是1的补码。

其实也能理解加小数点的原因,因为它要移位什么的就很麻烦,就像前面说的,我要说成这种形式:与这个数的高8位相加。而且如果长度不一样我还要改高几位,不如我用个小数点,把它定在那边,我默认就是对小数点靠近左边的那几个数相加,往右移走的数我完全不用管,大概就是这样的做法了。

标志寄存器

这里有两个标志寄存器需要注意一下:CF,OF分别表示 carry flag和 overflow flag,无符号溢出标志和有符号溢出标志。

这里稍微注意一下三个概念:

  • 最高位进位:指的是,数的最高位是否进位。
  • 符号位进位:指的是,次高位是否进位(进位即改变符号)。
  • 最低位进位:因为减法是取补,而对于电路来说,取反是很容易实现的,但是取反+1相当于再做了一次运算,于是取补就变成了取反再给最低位的进位设置成1。这样就相当于 + 1了,所以最低进位的值等同于是否进行减法运算,减法运算则最低仅为为1,否则为0。

进位标志与溢出标志

  • CF:加法减法好像是有区别的,如果是减法指令,那么仅仅观察目的操作数是否大于源操作数(无符号大于),是就为 1。如果是加法指令,只需要关心它的最高位进位是否为 1。总结来说——减法标记(sub指令时=1)异或 最高位进位标记 就是 CF 的值
  • OF:同时要判断两个值,一个是最高位进位,一个是符号位进位,若不相等则 OF=1。
文章目录
  1. 1. 数据编码
    1. 1.1. 原码,补码,反码,移码
      1. 1.1.1. 原码
      2. 1.1.2. 补码
      3. 1.1.3. 反码
      4. 1.1.4. 移码
    2. 1.2. 单符号与双符号
    3. 1.3. 移位运算
    4. 1.4. 乘法和除法
      1. 1.4.1. 原码一位乘法
      2. 1.4.2. 补码一位乘法(BOOTH算法)
    5. 1.5. 标志寄存器
|