运算器
接收并执行控制器(指挥中心)的命令,用于实现算术运算(加+减-乘*除/)、逻辑运算(与&、或|、异或^、非!)和移位运算(左移<<、右移>>、无符号右移>>>、求补),这些运算都依赖算术逻辑单元ALU。
ALU:算术逻辑单元,通过内部复杂的电路实习算术运算和逻辑运算;
ACC:累加器(也是寄存器),用于存放操作数或者运算结果;
MQ:乘商寄存器,在乘、除运算时,用于存放操作数或运算结果;
X:通用的操作数寄存器(多个),用于存放操作数。
运算器依赖于算术逻辑单元ALU,ALU之外还有一堆的寄存器,这些寄存器都可以统称为通用寄存器组(很多个,现在没有分那么清楚),eg ACC、MQ等 。运算的时候数据需要进行临时存储,临时存储需要放在通用寄存器组里的某一个寄存器里,运算完之后会把运算结果输出到对应的寄存器里,这些数据有可能通过数据总线传输给其他设备如存储器,有可能存储在通用寄存器组里。
一、ALU的功能结构
ALU的功能就是进行各种运算,所有的运算最终都是归结于加法运算(加法运算其实从电路上来说也是逻辑运算),所以认识一下加法器。
如图,寄存器(通用寄存器和其他的寄存器)用来存数据 ,通用寄存器组存放的数据大部分由内存(主存)过来的,临时存放数据(还有栈、指针、地址)。乘法和除法还有中间过程的一些数据,在运算过程中会产生大量的信息,中间的过程数据也会存放在对应的寄存器里。PSW是状态寄存器, 记录一些进位、溢出等。操作数两个输入信号输入之后进行运算,运算类型由控制信号决定,控制信号可能有很多,然后对运算结果进行输出。ACC是典型的累加器(累加寄存器),eg CPU在进行运算的时候最初从内存拿数据先放到通用寄存器,再把数据放到左边运算的那些寄存器里(也能把数据直接从通用寄存器里拿出来进行运算),ACC一般放一些被加数、被减数、被除数被乘数等,MQ是乘商寄存器,就是乘法除法运算的时候会一些操作数,一般放乘数或乘的结果除的结果(感觉不用理解太深)。
A0~A3和B0~B3,一个输入数有四位,两个操作数各四位,一次性能操作的单个输入数的位数是多少位就说CPU是多少位的(实际的要比上面的模型大很多不止4位),Cn代表进位(eg 1+1写0进一位),换句话说两个操作数进行运算的时候是前面的运算给的进位这个叫低位进位,是因为之前有数据操作完了之后要进位就伴随着Cn进来了,所以A和B进行运算其实是前面的低位的进位,发过来A和B运算完了之后也可能会进位,这时Cn+4(4代表那个位宽)代表进位,给下一个进位,这叫高位进位。
这里输出结果也是四位(输入也是四位),控制信号S0~S3也是四位,都是二进制位,位宽只有4位,4个二进制位最多表示也就是16种可能,也就是说可以进行16种不同运算(加减乘除、逻辑运算与或非、移位......),M是进行运算的类型,eg A和B这两个操作数要进行相加,那它是如何知道要进行加法运算的,就是控制器通过控制信号告诉运算器的,ALU里分两大类运算分别是算术运算和逻辑运算,辅助功能可以归结到逻辑运算里,也就是说有两种可能,这两种可以用M来表示,M这个线若输入的值是0,就进行算术运算,至于进行哪种算术运算由S0~S3决定,就是用其中某一种二进制位组合来表示哪种算术运算;若M=1,要进行逻辑运算,S0~S3也表示对应的逻辑运算。
- 算术运算归结为加法运算去·
- 控制信号决定是否进行逻辑运算,那些辅助功能也可以归结为逻辑运算
二、如何实现逻辑运算
介绍几个实现逻辑运算的逻辑电路,算术运算也是由这些逻辑电路完成的,常见的逻辑电路有这几个:
- 与 & Y=A B
- 或 | Y=A + B
- 非 ! Y=
- 异或 ^ Y=A⊕B
- 与非: Y== +
- 或非: Y==
把0和1看成是高低电平的话,在异或中只有输入不同电平时输出才为高电平,在与非中,只有输入都为高电平时输出才为低电平,在或非中,只有输入都为低电平时输出才为高电平。
三、串行/并行加法器
1、一位全加器
(很多文字但很容易理解~)两个操作数叫本位,每次进行进位的时候有个进位的值,比如当前计算1+0的时候取的进位是前面本位运算的时候结果(1+1)的进位,所以叫 低位的进位,表示每一个本位的和,竖着来一个本位1+本位1。看表进行比对,输入也包括低位的进位,低位的进位也是输入的一部分,是高位的进位,是错位移位的值。现在这个加法如何用电路去实现。怎么计算(就是本位的和)?
在计算机中没有所谓1+1=2这个说法,本身所有的输入都是电信号也就是高电平和低电平,我们只能通过输入的高低电平去判断输出的结果是高电平还是低电平。输入的时候有三个值,分别是两个操作数的本位和低位的进位,根据这三个值去进行运算比较判断,:当输入中有奇数个1时则为1,否则为0,就能发现上表中的规律,本位的和就根据输入的三个信号,输入的三个信号通过逻辑电路去判断最终的结果是1(高电平)还是0(低电平)。
那如何证明这里会有奇数个1呢?就是用异或运算,一个数与另外一个数异或两次的时候得到的结果是它本身,1^0^0=1,0^1^1=0,所以异或的结果是0,说明有偶数个1,结果是1说明有奇数个1,因此我们只需要三个值进行异或,=,互相进行异或的三个值就是的值。
怎么计算?也是根据现有的三个输入,输入中至少有两个1则为1(有进位) ,否则为0。如何判断这三个输入里至少有两个1呢?
情况一:用与&:判断和同时为1,若&=1,就同时为1,无论是不是1,肯定有一个进位,只是当前的位置是写0还是写1的问题。
或者(用+连接)情况二:判断和之间有一个为1,同时低位进位为1,和有一个为1可以用异或进行判断,异或的逻辑就是他们两个不相同结果为1,两个值相同结果为0,得出的结果再与低位进位进行相与操作,所以得到的结论公式为:
= + ( )
电路实现物理图:
从这里我们可以看出,没有所谓的加减法的动作,本质上是门电路的不同顺序的排列,所以我们说算术运算本质也是逻辑电路,这整个电路的过程没有所谓的加法,其实每一次输入的就是高低电平,最终算出来的结果也是高低电平,只不过是从逻辑上去理解是1还是0。我们把这最基本的加法的电路封装起来,叫一位全加器。
逻辑图:
要理解的一个点是在计算机底层运算时其实没有所谓的加减乘除,本身是用逻辑电路实现的,这个逻辑电路输入的内容都是高低电平;还要理解的一个点是如何计算和。
2、串行加法器
通过上面我们知道一位全加器运算效率不高,那能不能连续地运算呢?这就看我们现在要了解的串行加法器了,串行加法器其实在一位全加器的基础上加了一个东西,叫进位触发器。
进位触发器:保存的内容是进位的位,数据逐位送入FA中运算,串行、逐位送回寄存器。、和运算之后的结果除了本位和之外还有一个高位进位,那放在进位触发器里有什么好处呢?
一位全加器的电路可以计算加法,那现在可以计算一次,那是不是也可以计算十次一百次,那做一个循环的计算是不是就可以了,刚才输入的是最低位的和,那接下来就不停地往前进位就可以了,所以它是数据逐位送回寄存器中进行运算,这里有一个特点就是我们输入之后运算出来一个和,通过进位触发器又重新作为低位的进位传递给下一次的输入。
那现在问题是跑哪去了,下一次再运算是不是得出一个新的结果,而这个的上一次的运算结果怎么办呢?我们是不是得写回到寄存器中,写回到寄存器中那是不是就意味着我们每一次运算完之后都要往寄存器中去重新回写一次,所以这里其实是我们每算完一位然后串行的,逐位地送回到寄存器,其实就是把本位和送回到寄存器,每算完一次都要往寄存器中去重新回写一次,这个效率其实还是有点低的,串行加法器不是把多个一位全加器串行起来,串行加法器其实用的还是一位全加器,只不过是反复地利用它,它这里所谓的串行是把每一位每一次地串行输入进去,同时每次产生的结果本位和也是串行地逐位地回写到寄存器中,它的效率也只是比一位全加器好点。还有一个细节是我们这里是8位,那实际上大多数计算机不止8位,有32位64位那样的,64位的居多,如果要计算一个64位的数,那这里要运算64次,而且要往寄存器中回写64次。
3、并行加法器
把大量的一位全加器并行起来,每一个一位全加器都可以计算对应本位的和,这样效率也会提高,它看起来是并联的但实际是串联的。和在进行运算的时候需要一个低位的进位,在跟和运算完之后,就输出和,输出完之后就传递给下一个加法器,下一个一位全加器在进行运算的时候要有参与运算,所以就要等前面的一位全加器运算完之后把进位的结果交给紧邻着的下一个一位全加器才能进行工作,其实就是把个一位全加器串接起来,它的运算效率高,高在可以一次性把所有的位(结果)计算出来,所有的位计算出来之后再把所有的位一次性回写到寄存器里,不用像串行加法器那样一个位一个位地回写到寄存器里。
现在的问题在于每一个一位全加器的运算效率是很高的,这个是非常快速地,因为本身是一些基本的电路,但是这个全加器传递给下一个全加器之间是不是得有一个电路,这个电路其实就是总线,叫CPU内部总线,就把它看成线路就行了,那线路的传递效率有多高呢?这个不好说,这个效率其实是没有保障的,而且本身每一次它都是这个串行地去进行传递,每一次其实都是要花时间的,要传递很多很多次,所以它是串行进位:进位信号逐级形成,从最低级传递到下一级,一直传到最高级,所以它的性能瓶颈也就是运算速度在于每一个进位的产生速度,比如.....如果每个进位产生的全程速度非常快,效率也会比较高,但也不是特别高,所以可以改进。
那怎么改进呢?我们可以参考下面的这个逻辑图。改进:~ ,~是已知的
参考这个逻辑图,它是一个4位的ALU运算器,一次性输入4位操作数,那么我们可不可以也在并行加法器里也一次性输入4位呢?并行加法器从~既然是4位的话现在就可以从~一次性写4位进来,一次性写4位的话看起来也没有和刚才我们所说的并行加法器有什么太明显的区别,真正的问题就在于~和~它是两个操作数,而且~ ,~是已知的,每一位都是知道的。
操作数是预先知道的,每一位都是知道的,之前我们都是串行地去进位,现在呢其实还是串行进位,那我们是不是就可以让每一个一位全加器它们都预先去计算一部分呢?现在需要三个参数去计算,那现在可不可以先计算其中的两个参数,A和B这两个可以先计算一把,完了之后等C这个进位的值来的时候再进行一次运算。
记住我们的目标是计算每一位的和,计算完这两个那我们二进制的加法就可以往后去继续推进了。对于每一个一位全加器和我们都是预先知道的,不知道,我们在一次性输入所有的和的时候,我们先让和进行运算完成一部分的工作,比如说我们把算出来,然后计算,最后来了之后我们就可以计算,那有了低位的进位之后我们就可以直接计算。
=
= + ()
=
=
这个SN74181的工作原理其实就是把多个一位全加器给串接起来,串接的时候就不是像前面的那样后面的一位和前面的一位直接串接,而是在上面加了一个总线,可以看它看做是一个线路,那它是怎么工作的呢?首先我们把A和B每个数的4位同时输入进去,输入进去也就意味每个全加器都拿到了自己的和,与此同时拿到数据之后就计算自己和的与操作和异或操作的值,也就是和,然后直接传送到总线上,也可以这样理解就是传送到所有的全加器上。
需要注意的是最低位的全加器在进行运算的时候,和进行两次异或操作,可以这样说,先进行与操作再进行异或操作,进行一系列操作之后,把进位到下一个值作为参数,是不是相当于把前面的整个公式比如= + ()的这个值代入到下一个=这个位置上去,其实就是相当于是这个公式的代入,就相当于这个就变成了第二个全加器在计算的时候,第二个全加器的计算的时候是不是就相当于把第一个全加器在计算的所以的表达式都给它代入进去,那现在的话我们提前计算好了每一个全加器的与和异或的值,那么相当于我们下一个全加器就提前拿到了前一个全加器和的与和两个异或的值。可以这样再理解一下就是:
假设最低位的全加器它们这里都是、和,完了之后的话这个全加器在进行运算的时候比方说,这个低位的进位怎么来的,其实就是原来的低位的全加器在运算过程得到的,整个代进去就行了,什么意思呢?就是:
就相当于我们在求的时候就是用除了它自己的这些数据之外还需要前一个进位,那这些前一个数据值如果预先都一次性地比如说在放进来最初的时候就可以直接放在总线上,也就意味着所有的全加器都能拿到,完了之后如果输入数据之后所有的全加器都把自己的和都计算出来然后一次性放到总线上,也就是说对所有的全加器都是开放的,都能直接拿到,就是可以把前面的和直接代入到自己的公式里面,计算和是所有的全加器并行执行的,与此同时在计算每一个进位的时候其实效率也非常高,其实也就意味着所有的全加器在输入A和B的值之后立刻计算出和,然后放到总线上,然后紧接着所有全加器都是可以计算出自己的和,计算出自己的和也是并行的,都是同时产生的。在整个4位全加器里面每一位工作的过程中其实都是并行的。并行的核心逻辑就是俩步:第一步就是在输入A和B这两个值的时候所有全加器都会同时去进行运算,运算之后把运算结果放到总线上,可以理解成发送到所有的全加器;第二步就是:所有的全加器都可以拿到对应的和的值,完了之后它们就可以自己同时计算出和的值,然后再同时放到这个总线上,然后传递给后面的所需要的数据,两次并行计算。
对于64位的计算机,把4位的ALU并行起来,我们把所有的SN74181并行起来,比如说按刚才的逻辑把4个ALU并行起来,每4位出来的结果其实也是自己的和,完全一样的道理,这样的芯片叫SN74182,达到每一个SN74181它4位处理数据的时候其实就是分组,组内并行,这些组之间进行运算的时候其实进行了组内并行、组间并行的效果,当然这里的图才16位,看懂这个原理就行。
真正核心的地方在和的与操作和异或操作是最终目标和的参数。