漫谈计算机组成原理(八)原码、补码、反码

《漫谈计算机组成原理》这个系列的文章共分为两个部分。第一部分围绕着计算机主机的外围硬件,包括总线、存储器、输入输出系统等,这部分的内容已经完成,感兴趣的可以看看之前的文章。之前凡是涉及到CPU的内容,除了第一篇简要的介绍过CPU的工作意外,其他文章都是默认将CPU作为一个“黑盒子”,不涉及到CPU内部的逻辑、运算等问题。而从这篇文章开始,我们将重点讲述CPU的逻辑、运算、信息处理等的相关知识点。接下来的几篇文章都是写计算机的运算方法的,第一篇文章我着重介绍几个概念——原码、反码、补码及移码,后面的文章就展开看CPU究竟是如何被用来计算的。好了,话不多说,开始后半部分的第一讲吧!

概述

我们当然知道,计算机只能识别0和1,也就是我们所说的机器语言。所以在程序猿进化史中出现过一种非常NB的品种——机器语言程序猿,他们的程序是写在纸带上面的。但是这种生物存在的时间不长(我不知道还有没有真正意义上的机器语言程序猿),就被编译器取代了。因为计算机只能识别0和1,所以在计算机的运算过程中,参与运算的必然只有0和1两个数字。那么这小小的0和1,究竟是如何完成如此复杂多变的操作的呢?

机器数与真值

在说原码之前,我们必须提一下计算机中参与运算的两类数(由0和1组成的“数字”),无符号数和有符号数。无符号数就是没有符号的数,如0001,有符号的数就是有符号的数,如+10001、-0010等。此外,无符号数和有符号数的表示范围并不相同,无符号数表示的范围是0 ~ 65535,即0~ 2^16^ -1;有符号数的表示范围是-32768 ~ +32767,虽然范围不同,但是表示的数据都是2^16^个。除此之外,无符号数和有符号数的另一个重要的不同点就是在寄存器中的存放方式:无符号数可以直接存放在寄存器中,但是有符号数是有符号位的,所以需要连同符号位一起保存在寄存器中。+和-是两种状态,0和1也是两种状态,所以+对应0,-对应1,存储到寄存器中就很简单了。
【注】原码、反码、补码、移码均属于有符号数。

原码

原码可以说是计算机中最简单的、也是一种最基本的数据表达形式,比如-0001,符号位是-,所以第一位就是1,而真值位就是-0001的绝对值,即0001,所以-0001的原码就是10001。
因为原码可能是整数的原码,也有可能是小数的原码,这就造成了一个问题——该如何表示原码中的小数点,即便是整数也有小数点。整数的原码很好表示,符号位和真值位之间由逗号分割,小数位在真值后,可以不写出来,即表示为1,0001。至于小数的原码,小数点就表示为小数点。如-0.11001,表示为1.11001
原码表示方式的总结
教科书式的表示方式是在是让人眼花缭乱(个人认为),我在这里直接用文字表述原码的表示方式。

  • 整数的原码表示:符号位如果是+,则直接在真值的绝对值前加上符号位0和“,”;符号位如果是-,则直接在真值的绝对值前加1和“,”
  • 小数的原码表示:符号位如果是+,则直接在真值的绝对值前加上符号位0和“.”;符号位如果是-,则直接在真值的绝对值前加1和“.”

补码

你可能没有听过补码,但是肯定听过补角。如果说两个角互补,那么这两个角的角度相加肯定是180度的。如下图所示:

角A:120°,角B:60°,两角之和为180°。这就是补角的概念。
但是补码和补角略有不同。补码是一种有模的数据,是有正负的。如:当前钟表表示时间为6:00,想要让时间表示为12:00,我既可以让时针逆时针调整6个小时,也可以顺时针调整6个小时,如果顺时针记为+,逆时针记为-,则+6和-6所达到的效果是一致的。我们就称+6和-6是以12为模的补数。所以,我们可以使用+6来代替-6,也可以用+9来代替-3(同样是12为模)。
补码也是同样的道理,就是用一个正数来替代一个负数。为啥要这样做呢?因为这可以减少一种运算,就是减法运算。这样就可以使计算机的运算,不论加减,都能当做加来运算。但是乘除不能转换。
关于补码的表示,规则如下:

  • 正数的补码是其本身(实际上,正数的补码、原码、反码都是其本身)
  • 负数的补码:运算方式—>符号位保持不变,其余为取反,末位+1
    如:-100100的补码为:除符号位各位取反1,011011;末位+1:1,011011+1 = 1,011100.所以1,011100就是最终的结果

反码

反码存在的意义:在原码和补码的互相转换过程中起到一个过渡的作用。
反码的表示更加简单:

  • 正数的反码表示:其本身
  • 负数的反码表示:除符号位不变,其余位各位取反(大家可以找个数字尝试一下)

移码

移码很有用,具体作用就是比较大小。
下面两个数:1,0001和0,0001,判断大小。乍一看,好像是1,0001>0,0001。但是你别忘了,1,0001可是负数……
这个问题就非常好玩了,这种简单的数对于人其实还好判断一些,但是对于计算机,他并不能像人一样思考。
如果我们这样做:将1,0001和0,0001都加上一个0,1111,最终的结果都成为符号相同的数了,肯定是非常好比较的了。
所以,[x]~移~ = 2^n^ + x(x是真值,n是整数x的位数,小数没有移码)
这样,我们就能很好的判断数据的大小了。
如果你亲自计算了,你会发现:正整数的移码和补码只相差了一个符号位。

总结

这篇文章是后续文章的基石,相对简单。大家只需要记住数据的原码、反码、补码的运算即可,移码属于了解范畴。
如果你喜欢我的文章,欢迎关注微信公众号:最高权限比特流。

发表评论

电子邮件地址不会被公开。 必填项已用*标注