CPU是如何进行计算的

为什么CPU可以运算,CPU是如何进行运算的,揭开CPU神秘的面纱。

现在计算机已经成为人类不能摆脱设备,绝大多数人都或多或少的懂一些计算机的操作,不管你是用来看电影还是打游戏,不管你是用来做研发还是做运维,都是应用级别,那么计算机内部是如何实现运算的呢?或者说CPU是如何实现运算的呢?

1.数学运算与数制转换

在数学上,我们最常用的数制是十进制,基础运算为加减乘除,而计算机不同,计算机只能识别1和0两个数字(确切的说是两种电平),所以计算机只能识别二进制,而且计算机其实很笨,他只会计算加法,因此我们需要将十进制转化为二进制,这样才能让计算机为我们计算。数值转换的具体方法我会单独写一篇文章进行介绍,这里请大家先用计算器进行计算(这也是我常用的方法,毕竟手动计算太慢了)。
在上一篇文章中,我们介绍了逻辑运算及电路上的实现(没看过的戳这里),通过晶体管的不同组合,我们实现了与或非等一些基本的逻辑运算。后面我们进行的加减乘除的运算也是通过这些逻辑运算进行组合来实现的。

2.加法运算

加法运算是计算机底层能进行的唯一的运算,就是通过这种唯一的运算加以变换实现了更多更复杂的其他运算。在数学运算中,最简单的应该就是0+1=1了,下面我们就以0+1为例来讲述计算机是如何进行计算的。上面说到需要进行进制转换,下面有一个简单的表格,其中对应了16以内10进制,16进制,2进制的对照表:

十进制 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
十六进制 0 1 2 3 4 5 6 7 8 9 A B C D E F
二进制 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

从以上的表格中可以看出,将十进制的0+1 = 1转化为二进制表达式为0000+0001 = 0001。这里我们只考虑最低位(从左向右数为从高位到低位),也就是0+1=1(这里的数字是二进制),在之前介绍过的逻辑运算中,有那种运算是可以满足这个条件的呢?输入为0和1,输出为1,或运算可以实现,异或运算也可以实现,这是输入条件为0和1的情况,如果是计算1+0或者1+1呢?1+0=1, 1+1=0(只考虑最低位,不考虑进位),这种情况下什么运算才能满足呢,很容易看出异或运算能够满足这个条件,所以异或门(由晶体管构成的异或运算电路)就构成了CPU中的加法器。也就是说异或电路可以实现CPU中的加法计算的功能
虽然弄懂了 一位加法的实现,但是刚才我们忽略了进位的实现,例如0001+0001=0010,这种运算又如何实现呢?考虑一下什么时候才需要进位,就是两个加数都为1的时候才需要进位,进位为1,这不就是我们之前说过的与运算么?所以我们把一个与门同一个异或门进行并联不就实现了带进位的加法么?如下图:

1.png

此图中PQ为输入,SUM为输出,CARRY OUT为进位输出,真值表如下:

P Q SUM CARRY OUT
0 0 0 0
0 1 1 0
1 0 1 0
1 1 0 1

这样我们就实现了一个很简单一位的加法器,我们称之为半加器,之所以称之为半加器,是因为在输入的时候没有考虑到进位的情况,所以也就是说输入应该有三个才对,所以我们把两个半加器进行组合就成了下面的全加器:


2.png

真值表如下:

CARRY IN P Q SUM CARRY OUT
0 0 0 0 0
0 0 1 1 0
0 1 0 1 0
0 1 1 0 1
1 0 0 1 0
1 0 1 0 1
1 1 0 0 1
1 1 1 1 1

一位实现了,八位也就很容易了,如下:


3.png

图中,c_in为第一位进位输入,这里设置为0,ab为输入,从左向右分别为从低位到高位,sum为输出,从左到右分别为从低位到高位,这里举个例子:
0011 0100+ 0010 1001 = 0101 1101(52+41 = 93),大家可以按照从低位到高位的输入顺序进行计算,然后将输出从低位到高位写出来,验证一下我们的加法器是否好用。聪明的同学会问到,最后一位进位怎么办呢?这里有个概念叫做溢出

溢出:假设我只有一个八位的区域,理论上来讲最大的存放数字是11111111,也就是2^8-1 = 255,但当我计算出来的数字是256(1 0000 0000)时就会出现溢出的情况,得到的结果会为0,因为第9位的1存不下了。

3.减法运算

前面讲到,CPU只能进行加法运算,那么减法怎么办呢?减法怎么才能转化为加法呢?这里首先介绍几个概念,分别是原码,反码和补码。这三个概念对于正整数和负整数是有区别的,在CPU的存储中,如果存储一个有符号的整形数据,那么最高位将称为符号位,也就是说,一个8位的区域,如果存放一个无符号的整形数据,那么他的存储范围是0-255,如果存放一个有符号的整形数据,那么他的存储范围是-128~127(因为最高位用于辨别符号,只剩下7位用来存储数据)

  • 原码

原码很容易理解,就是最高位的符号位加上剩下的数据,比如100(0110 0100),比如-100(1001 1100)

  • 反码

反码在原码的基础上,如果符号位为0,则反码等同于原码;如果符号位为1,则符号位不变,其余所有位取反,例如100的反码0110 0100,-100的反码 1110 0011

  • 补码

补码是在原码的基础上,如果符号位为0,则补码等同于原码;如果符号位为1,则符号位不变,其余所有位取反,再给最低位加1,就是反码加1,例如100的补码0110 0100 ,-100的补码1110 0100

综上所述,正整数的原码,反码,补码都相同。
为什么要出现反码和补码这个东西呢,就是用来为CPU做减法准备的。
假设我们不做任何变化去算减法,如下:

1-1 = 1+(-1) = 0000 0001 + 1000 0001 = 1000 0010 = -2

这个结果显然是错误的,后来人们想到了反码,如下:

1-1 = 1 + ( -1 ) = 0000 0001(反) + 1111 1110(反) = 1111 1111(反) = 1000 0000(原) = -0

这里又出现了-0的问题,会有两组数表示0,1000 0000和0000 0000,0本身是没有符号的整形的数据。为了解决这个问题,人们又发明了补码,如下:

1-1 = 1+(-1) = 0000 0001(补)+ 1111 1111(补) = 1 0000 0000(补) = 0000 0000

这里会出现溢出的情况,溢出去的1忽略,这样就完美的解决了两组编码表示0的问题。同时也完美的解决了减法的问题。
对于补码的获得,可以利用非门和加法器实现,这样减法就可以转化为加法来实现了,CPU就可以愉快的计算减法了

4.乘除法运算

对于乘除法运算,乘法运算,CPU会转化为加法进行运算,除法会先转化为乘法,然后再转化为加法,请读者独自思考,这里提示一下,会利用三个寄存器来一步一步进行计算,同时会用到移位。


参考文献:
知乎


欢迎大家留言点赞,欢迎大家点击关注,大家的赞美是我创作的最大动力,谢谢!

推荐阅读更多精彩内容