代码是怎么在计算机里跑起来的

首先咱们先来点表面的虚的,说明一下计算机的构成

计算机由集成电路(IC,Integrated Circuit)组成,计算机的硬件有三个基本要素,CPU是计算机的大脑,负责解释、执行程序。内存中存放着程序(程序是指令和数据的集合,比如 a = 1 + 2,"+"操作是指令,1、2是数据)。I/O是Input/Output(输入/输出)的缩写,负责将计算机和外部设备(周边设备)连接在一起。一台计算机,除了CPU、内存、和I/O,还需要若干辅助元件,驱动CPU运转的时钟信号




再看一下,从编写好的代码到运行在计算机的过程



然后再看下CPU的构成

CPU

既然数据的运算是在CPU中进行的,那么在CPU内部就应该有存储数据的地方(比如运算 1+ 1+ 1,先运算1+1,把结果存起来,再进行+1运算)。这种存储数据的地方叫作“寄存器”,CPU和内存是由许多晶体管组成的电子部件,通常称为IC (Integrated Circuit,集成电路)。从功能方面来看,如下图,CPU的内部由寄存器、控制器、运算器和时钟四个部分构成,各部分之间由电流信号相互连通。

寄存器可用来暂存指令、数据等处理对象,可以将其看作是内存的一种。根据种类的不同,一个CPU内部会有20~100个寄存器。

控制器是计算机的控制中心,它决定了计算机运行过程的自动化;它不仅要保证程序的正确执行,而且要能够处理异常事件比如把内存上的指令、数据等读入寄存器(运算1+1+1的话,就把内存中的1、1、1读到寄存器,怎么读?后面会详细说),并根据指令的执行结果来控制整个计算机。

运算器负责运算从内存读入寄存器的数据(怎么运算?看后面)。时钟负责发出CPU开始计时的时钟信号(怎么发?看后面)。不过,也有些计算机的时钟位于CPU的外部,我知道的单片机好像都是外部的



了解了CPU的构造后,大家对程序的运行机制的理解是不是也加深了一些?程序启动后,根据时钟产生的心跳驱动控制器会从内存中读取指令和数据。通过对这些指令加以解释和运行,运算器就会对数据进行运算,控制器根据该运算结果来控制计算机。看到“控制”一词时,大家可能会将事情想象得过于复杂,其实所谓的控制就是指数据运算以外的处理(主要是数据输入输出的时机控制)。比如内存和磁盘等媒介的输入输出、键盘和鼠标的输入、显示器和打印机的输出等,这些都是控制的内容。

CPU中每个寄存器的功能都是不同的。用于运算的数值放在累加寄存器(A寄存器也叫作“累加器”,是运算的核心)中存储,表示内存地址的数值则放在基址寄存器和变址寄存器中存储。

看到这些,只能说对代码在计算机中是怎么跑起来的,有了一个简单的认识,下面才是真正的理解,有请硬菜出厂


硬菜来喽

为了更好理解呢,咱们先用个实例开始一步一步的讲解,在计算机是怎么运算0011 + 0001 = 0100 的,包括怎么加载到计算机内存,怎么运算,怎么把结果存储起来。 从这个点出发,咱们一步一步的进行解析,下面说的逻辑门,可以不用记住电路图是怎么连接的,但一定知道有那么回事,因为既然写出来了,肯定是有用的,下面开始

继电器

 首先咱们先来了解一下继电器,百度百科是这么介绍的: 继电器(英文名称:relay)是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出回路)之间的互动关系。通常应用于自动化的控制电路中,它实际上是用小电流去控制大电流运作的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用

下图是实物,电子行业比较常见的外观是这种的,在电路板上一个黑色或者蓝色小盒子


那么实现原理是啥呢,首先得知道电生磁。缠绕在铁棒上的线圈,通电后会产生磁性,如同一块磁铁一样。如下图所示,开关闭合,铁棒和线圈就会变成一块磁铁,说到这里有没有想到以前物理学的安培定则



在电生磁的基础上,就能造出继电器了,原理如下:看下面左边的图,上面的电池和灯泡是断开的,红色箭头处指的是一个弹簧,嘴边的开关闭合时,左边的线圈会产生磁性,将上面的弹簧吸下来,这样上面的电池就和灯泡连接起来了灯泡会亮起,,如右图,所以继电器就是个开关,也可以做到四两拨千斤(如果上面的电池是100V,左边的电池是5V)



与门

如果两个继电器串联,就是咱们所说的“与门” ,只有当两个开关都闭合的时候,灯泡才回有电流,才回亮起来,如下图。(补充,下图是两个开关串联,可以是三个或者是四个)


所以"与门"表如下


"与门"的表示符号为



或门

如果两个继电器并联,就是咱们所说的“或门” ,只要有一个开关闭合的时候,灯泡就会有电流,就会亮起来,如下图



所以“或门”的对用关系如下


或门的表示符号是


非门


之前说的开关都是默认是关着,当我输入端有电流以后,开关闭合,相当于我输入1输出就是1还有一种就是,开关默认闭合,当我输入端有电流以后(后面的图中,电池就用V代替),开关断开,如下图,开关默认是闭合的,灯泡也是两的,当我把线圈通电,会把弹簧吸下来,灯泡回关。现象就是 我输入1输出是0,这种连接方式的继电器叫,反相器。



输出和输入相反,符号表示为


或非门

如下图,有两个串联的反相器组成的电路,默认灯泡是亮的,只要有一个开关闭合,灯泡就会灭(或门是两个灯泡都断开时,灯泡才会不亮,这个电路是和“或门”反着,所以叫“或非门”)


或非门的输入输出对应的表为:


符号表示为:


与非门


如下图,有两个并联的反相器组成的电路,默认灯泡是亮的,当两个开关都闭合后,灯泡就会灭 (与门是两个灯泡都闭合,灯泡才回亮,这个电路是和“与门”反着,所以叫“与非门”)


对应的输入输出表为


简写符号是:



总结规律:涉及到“与”的就是只有当两个都怎么样,结果才怎么样。“或”只要一个怎么样,结果就怎么样。

加法运算

基础条件已经具备,开始讲解0011 + 0001

咱们做十进制加法时,会从最右边的两位相加,然后再倒数第二列的两位相加,那计算机是怎么对两个数进行相加的呢,其实和咱们运算是一致的,也是先从最右边两位数相加 1 + 1开始


不管是十进制还是二进制,咱们进行运算时,都是先两位相加,然后再继续,比如59+13,先9+3 = 12,进1留2,5+1 = 6,再把前面的进位加上,6+1 = 7,也就是72。

不管是两个几位数的数进行运算,最终都会转化两个一位数的数进行运算。当运算的结果,超过了当前进制能表达的最大数,就会溢出(也就是进位),十进制单个数能表达的最大的值就是9,单个二进制数能表达的最大的值就是1。十进制的9+3 = 12,结果已经超过9所以进1留2,1称为进位,2称为加法位


当前位的运算结果实际上是加法位,比如上图最右侧两位进行运算是9+3,你在下面写的就是加法位2,因为进位会参与到下一次运算,不在当前位的结果中

二进制也一样,咱们用二进制进行加法时,是逢二进一 ,所有可能出现的情况只有下面四种情况

0 + 0 = 00  ->进位是0,加法位是0

0 + 1  = 01   ->进位是0,加法位是1

1 + 0  = 01    ->进位是0,加法位是1

 1 + 1  = 10     ->进位是1,加法位是0

所以咱们用下面左边的表来表示四种情况下相加的“加法位”。右边的表,表示四种情况下二进制加法中的“进位”


咱们需要设计一个电路,当输入二位二进制时,可以同时输出加法位和进位,咱们发现“进位”表的结果恰好和“与门”的输出结果相同,加法位的表,好像没有相同的,得重新设计一个,所以就出现了下面的设计,左边是设计电路,右边是对应的输出结果,这样的设计,输入和输出,就和加法的加数和加法位对应的上了,


这个电路被叫做异或门,,特定的电器符号如下图


异或门输出的是加法位,与门输出的是进位,两个并联起来,就同时有进位和加法位了。如下面左边的图片,电器表示符号是右边的图片。这其实就是一个2个二进制相加的加法器了


哇,好激动,两个1位的二进制数相加的电路已经出来了。计算机是没有思想的,只能靠各种电路来搭建出想要的东西。


0011 + 0001 最右边的1+1用上面的电路就可以出来了,加法位是0,进位是1也就是10,然后进行倒数第二列的加法。“0 + 1 + 最右边产生的进位”,因为前面运算产生进位了,所以现在三个数相加,刚才咱们的“半加器”只能输入A、B两位,进行两位相加,现在是三位,那就先两位相加,把相加的结果再和另一位相加,设计电路如下,和咱们在纸上进行笔算的流程是一样的,A、B代表上图中倒数第二列要进行相加的1、0,1和0相加后,进位是下图红色4所指的线,然后将加法位(红色数字2所指)和进位再次进行相加,产生加法位(红色箭头1所指,这是最终的数),和进位(红色箭头3所指),所以三个数相加,会产生一个加法位,和两个进位。最终的进位,应该是两个进位的和


但是你会发现不管咱们进行十进制计算还是为二进制计算,二个进位都不可能同时为1,比如我当前列的两个数相加,如果产生进位,那么剩下的加法位加上前一列产生的进位,就不可能再产生进位,可以自己验证一下。进位只可能有一个是1,所以设计图就如下所示

用简单的符号表示如下图


所以就0011 + 0001可以表示为下图,每一列都单独按照顺序输入到全加器中。A端输入分别是0011,B端输入分别是0001,到此我们就实现了加法器了,就可以算出0011 + 0001



八位加法器

为了后续方便讲解,咱们都至少用一个字节来表示数字,一个字节是8位,如果两个八位二进制数相加,咱们就得需要8个全加器串联,如下图。

如果你要进行16位二进制的加法,那就串联16个,一个8位加法器需要用到144个继电器,不信你可以数数。如果做减法呢,原理差不多,就是读转成补码相加


封装成芯片,就是下图样子,这样输入可以更直观


用简单的电器符号表示就是



振荡器

现在咱们有加法器了,咱们的计算机可以算数了,他现在会做 0001+ 0011,但是 如果做(0001+0011)+0111怎么办,一种办法就是用两个累加器,第一个累加器的结果输出到第二个累加器,但是不太现实,因为我如果一千个数相加,或者不确定的数相加,就没法整了。还有一种办法就是记住0001+0011的和,然后再+1,所以咱们接下来学习的是让计算机有记忆力

咱们先来看一个有趣的电路,这个电路,开关闭合后会发生什么

开关闭合以后(如图1),线圈通电,产生磁性,把上面弹簧吸下来(如图2),吸下来以后,线圈断电,磁性消失,弹簧又弹上去(如图3)如此反复 ~

如果弹簧上绑一个小锤子,是不是就变成小学下课放学时的铃铛啦了 ~。我们称这种电路为振荡器

当上图中的振荡器的开关闭合以后,线路中随便一个点电压就会变成下图所示。比如说弹簧从即将断开开始算起,再到即将断开,是0.05s,那么1s能循环20次,我们把每秒震动的次数成为频率,单位是Hz,也就是20Hz。可以改变弹簧的粗细,材质来改变频率


锁存器

在看寄存器前,咱们再看看“或非门”的输入输出对应关系,只要有一个输入是1的情况,输出就是0(看到“或”就是“只要有一个”),如果忘了或非门怎么实现的,可以到上边找找。然后咱们接下来看下面的电路,下体中

出,又回到输入,这种连接方式成为反馈,也就是输出的结果会影响到自己

咱们接下来看一下上图中开关闭合、断开时候的各种状态表现。

1、如下面第1张图是电路最初始的状态,现在两个开关都没通电,1、2处电压是0,所以3处是1。3处是1,4处是0,所以输出端5也是0,灯泡不亮

2、第2张图,第一个开关闭合,1处电压是0、2处电压是1,所以3处是0。3处是0,4处是0,所以输出端5也是1,灯泡亮起来了,亮起来以后1处就变成了1,2处还是1,3处还是0,虽然1处从最开始开关闭合时的0变为灯泡点亮后的1,但是输出结果是不变的

3、第3张图,第一个开关有闭合变为断开,1处电压是1、2处电压是0,所以3处是0。3处是0,4处是0,所以输出端5也是1,灯泡还是亮的,咦 ~神奇不,其实就是因为是反馈电路引起的

4、第4张图,第二个开关闭合,1处电压是还是1、2处电压是0,所以3处是0。3处是0,4处是1,所以输出端5是0,灯泡灭了,灭了以后1处就变成了0,2处是0,3处变为1,虽然1处从最开始1变为0,但是输出结果是不变的

这种电路有啥作用呢,就是记住你上次的操作,如果灯泡亮着,就说明你上一次操作的是闭合过上面的开关,如果是灭的,要不就是一个开关也没动过,要不就是最后一次操作的是下面的开关。就和咱们的汽车,如果发动机是启动的,说明你最后一次是顺时针拧的钥匙,如果发动机是熄火状态,要不就是没碰过车,要不最后一次就是逆时针拧过钥匙(仅限非一键启动的车 ~)。这就相当于给计算机添加了记忆力,可以记住上次的事

将上面的图,变一下型就成下图,只不过在红色数字3处,引出了一个 ~Q,注意,下图下面的S(set)是上图的第一个开关,下图的上面的开关R(reset)是上图第二个开关。为啥Q和~Q是相反的呢,可以验证一下~Q是由Set和Q或非的结果,Q是1时,不管set是啥,~Q都是0,Q是0时,set肯定是0,所以~Q是1。  


输入输出对应的表格如下 set打开,或者reset打开,或者都不打开,不能同时打开,都关闭时,会保持上一次的状态(比如上面set开关打开,灯泡亮了,闭合后,会保持之前的状态,还是亮的)


现在这个触发器呢还是有点不完美,就是只要set或者reset操作了,就会把对应的状态记下来,也就是Q会有相应的变化。比如说要记开会的会议内容,只记重点就行,不需要全记。所以咱们做成,需要记的时候,才记。如下图,多了两个与门(都为1时才是1),当保持位为0时,set和reset不管输入啥,两个与门输出的都是0,如红色数字1、2所示,所以输入到大脑的是0,那输入的都是0,输出就会保持上一次的不变。当保持位置1,set和reset才有效


咱们说了set和reset不能同时为1,但是电路是允许这样输入的,所以咱们得避免一下,防止人为出错,改造如下图,数据端输入1,就相当于set是1,reset是0。数据端输入0,就相当于set是0,reset是1。那之前输入都是0的情况咋没了,咱们想想,set和reset输入都是0,输出会保持不变,咱们保持位是0的时候,其输出就是不变的,就可以代替都是0的情况了。这就好像是一条有门的通道,当保持位是1时,门才打开,才能通过,保持位是0时,门是关着的,无法通过。这种带开关的就叫"电平触发的D型锁存器"


上图的锁存器,只有一个数据端,所以只能保存1位二进制数,如果保存多个呢,那就多用几个,把八个摆在一起,就变成8位的锁存器了,如下图,右边是,简化电气图


有了记忆力之后,咱们就可以用一个加法器,进行多个数的相加了,如下图


开关处可以依次输入好多个数,每次输入完,把相加开关闭合一下,也就是把门打开一下,让数据进去,你会发现8位锁存器,比之前的多了一个清零开关,之前的电路也可以做到清零,保持位置1,数据端输入0就可以了,但是为了方便清零,又单独接了条线,线接在哪呢,如下图,直接接在最初的reset端,不受保持位影响




计数器

咱们已经可以让咱们的计算机进行多个数的计算了,但是还不完美,每个数的运算,都得手动操作一下开关,然后万一输入错误,那就得从头开始了。所以怎么继续改造

之前说的电平触发的D型锁存器,现在再说个边沿触发的D型锁存器,电平触发的是一道门,输入1时,门打开,🐖进去了,边沿触发是两道门,打开两道门🐖才能进去,两道门就是两个电平触发的D型锁存器组成,如下图左边一个,右边一个。

当时钟为0时,左边触发器保持位为1,第一道门打开,数据端进入到第一个锁存器,当时钟为1时,第一个锁存器的保持位为0,门关上了,右边的第二个锁存器的保持位(红色箭头2处)处为1,第二道门打开,🐖就进去了 ~ ,时钟信号由0变1,🐖分别经过1、2道门。这就是边沿触发的D型锁存器



符号表示为


clk是用来输入0~1变化的心跳,那这个心跳由谁来产生呢,就有之前说的振荡器,加上振荡器以后,就变成下面这个样子

输入输出的时序图如下,也就是,时钟信号变两次(开两扇门),输出才变1次(🐖才跑出来),下面这张图,真正理解了边沿触发器才会看明白


然后根据输入信号的变化,和clk的变化,可以看出是如下关系,用红色箭头指的“下降”和“上升”的位置,就是指 数值 要变化了,只有时钟信号由0->1的瞬间,Q的输出会变成的输入的D一样。时钟信号由1->0再从0->1这算一个周期。所以时钟信号每变化一个周期(两次),输出才会变化一次


如果输入的时钟心跳频率是20Hz,即每秒20次,那输出端Q变化的频率是减半,变成10Hz,由于这个原因,这种电路称为分频器。如果连接好几个,可以产生更多频率的输出,因为~Q和Q的反的,Q和输入D是一样的,所以~Q和和D是相反的。将输出的~Q反向输入到D就会让D处于一直变化的状态



心跳、Q1、Q2、Q3输出的频率分别递减为前者的一半,分别为20Hz、10Hz、5Hz、2.5Hz。如图


把0、1标上去之后就会发现了一个新奇玩意


把图顺时针先转90度就是



刚才是一个震荡器(心跳)+ 三个D型触发器,构成了4位的二进制数所能表达的数,如果把8个触发器连接到一起,就构成了8位的计数器,如下图,如果你担心传递把的触发器,会有延迟,别担心,与更先进没有延迟的并行(同步)计数器


下面开始讲内存,咱们都知道,咱们的程序会被加载到内存,那内存是由啥构成的,怎么访问呢

内存

首先,回顾一下,前面说的D型电平触发器,当写操作端为1时,Q才会变为数据端,否则不变化。也就是写操作端为1时,会把数据端输入的数据存储起来了


简化的符号是


如果把8个电平触发器连起来,共用一个写操作端,那就可以同时存8位,如图


但是如何检测,我输出的数据是啥呢,当然可以连上灯泡检测,8个输出,用一个灯泡得连8次才能全部检验完。所以发明了另一个比较简单的装置,这样就不用拿着一个灯泡安装,拆下,再安装


8-1选择器


具体的实现是


输入输出对应的就是


这样只需要1个灯泡连接,只操作那三个开关就可以实现挨个输出对应的结果,


接下来再看输入,一种方法就是,每个写操作端加一个开关,来决定当前的锁存器是否被选中,还有一种就是,只有一个选择开关,然后判断这个选择开关作用到哪个锁存器,于是就发明了 3-8译码器


数据输入端的数据。由输出端O(0-7八个脚)的哪个脚输出,是有S0、S1、S2决定的,上图可以看出数据输入端和每个“与门”相连,“与门”的特点是只要输入端有1个是0,则输出肯定是0,所以要想与门的输出和数据输入端一样,则“与门”的其他三个输入必须为1。咱们举个例子,比如S0、S1、S2对应的是0、1、0,那输出端的哪个引脚和数据输入端一样, S0是0所以下图用红色箭头指的线相关联的“与门”输出肯定是0,就排除了和S0直接连接的与门(红色箭头指的1、3、5、7),S1是1,取反是0,所以和S1取反连接的与门,都会输出0,所以下图用绿色箭头指的线相关联的“与门”输出肯定是0,就排除了和S1非们直接连接的与门(蓝色箭头指的0、1、4、5),S2是0所以下图用蓝色箭头指的线相关联的“与门”输出肯定是0,就排除了和S2直接连接的与门(蓝色箭头指的4、5、6、7)


所以还剩2,有可能,咱们再验证一下2是否和数据输入端一直,看下图,2引脚的输出,是 S0取反、S1、S2取反、数据输入端决定的

S0取反、S1、S2取反对应的是1、1、1,所以输出引脚2的输出值,是由数据输入端决定的


所有的情况都走一遍你会发现,结果是这样的


然后就组装了一个。可以一边存,同时可以看到存的值是啥的系统,如果写操作端置1,就是一边存,接着把存的值显示出来,如果写操作端置0,那么只显示选中的地址存的值


然后这就是咱们常说的RAM(Random Access Memory)~简化结构为,之所以被称为随机访问存储器,是因为读写操作很自由,我们只需要改变地址及相关的输入,就可以从8个锁存器中读出或写入需要的大数据


这个RAM可以存储8位,要想存储更多怎么办,可以拼更大的,比如下图


2-1选择器,输出会根据选择端是0还是1来输出A还是B



如果想要更大的,可以依次类推。咱们再回顾一下,之前做多个数的加法时,需要把每个加数,比如50个数相加,依次从开关处输入,每输入完一个按一下“相加”把 "和" 存起来,等待下一次相加,如下图




虽然可以实现多个数相加,但是还是得依靠人工把每个数用开关输进去,万一中途某个数输错了,那前功尽弃,所以继续改进,咱们上面刚刚学习了RAM,可以随表访问某个地址读写,万一某一个写错了,可以直接访问那个修改就可以了,

所以改进一下,第一步,先用控制面板(开关)把加数挨个输进去,万一错了可以随时改,如下图,可以用地址选择开关选择要写入的锁存器



数据有了以后,就可以往加法器里自动输入进行相加操作,真昂起每震荡一次,16位计数器就会从0000 0000 0000 0000 每次加1,直到 1111 1111 1111 1111 计数器的输出作为RAM地址选择段的输入,就会依次选中每个地址,将咱们手动输入到RAM的数据依次输出到加法器。同时,振荡器也连接着锁存器,同时会把加法器加完的数值锁存起来。


        这样就不怕输入错了,到目前为止咱们已经涉及到了累加器、内存、锁存器、控制器,但是还有些不足,比如,我一共就有10个数相加,加完怎么让他停下来呢 ~   ,还有一个问题就是我想做 27h+A2h+18h =? 、1Fh + 89h = ?、33h+2Ah+55h =? 我就得先把27h、A2h、18h输入到RAM做完加法以后,再把1Fh、89h输入进去,再做加法,依次类推,这是比较麻烦的,就和普通计算器一样,不像电脑 ~。

        我们希望这个家伙可以更智能一点,比如我输进去27h、A2h、18h、1Fh、89h、33h、2Ah、55h计算机能知道我前三个数是一组,接下来的后2个数是一组,最后三个是一组,并且把每组的计算结果接着保存到RAM中,方便我一会查看(当组数是100组时,如果不保存,很容易记错),但是只靠输入27h、A2h、18h、1Fh、89h、33h、2Ah、55h这几个数,别说计算机,就是人也没法确定你要干啥。

        所以得附带一些说明,告诉他我这个数是干啥的。比如告诉计算机27h是第一个加数,A2h是这组运算的第2个加数,18h是第一组的最后一个加数,加完最后一个加数后,你得给我把"和"存起来。第一个数27h需要的操作就是把他加载到累加器中,不需要计算,因为现在只有一个数,第二个数A2h需要做的操作就是加载到累加器中并且进行求和运算,第三个数18h需要做的事是继续和前两个数的相加结果求和并且存起来。然后累加器清零开始加载第二组的第一个,以此类推。当做完第三组的时候,需要将停止计算。

首先如果咱们想把计算结果保存到RAM中,那么咱们计算的结果,应该得连接到RAM,如下图,锁存器存储的是计算结果,结果不仅输入到加法器用来做接下来的运算,而且还连接到了RAM方便把每组计算的最后结果存储起来。什么时候存呢,当然是当每组的最后一个加数加完,将RAM的W写操作端置1,然后就存起来了

但是把每组计算的结果存哪里比较好,当然是放在每组的最后面比较好,这样每组的加数和相加的结果都存在一起。如下图,方格里是具体要操作的数,左边0000h:代表在RAM中的地址



然后再给每个要进行运算的数做一个操作说明,

所以我要把每个加载到内存的数,都做一个说明,让计算机知道我这个数是干啥的。怎么表示这个数是干啥的呢,所以数据的说明(操作码)就·产生了,根据上面的加法遇到的情况,可以表示为加载、保存、加法、停止,并且还有对应的代码值,如下图,汇编语言的既视感有木有

所以咱们要做的就是,对每个输入到RAM中的数据要做一个说明,说明他是用来做啥运算的,刚开始发明了一种方式就是用两个RAM,一个和之前一样继续存放咱们的数据,另一个RAM存储对这个数据的说明(操作码),如下图,左边的RAM存储着对第二个RAM同样地址的数据的说明(也就是操作码的简写),右边是存放数据的RAM,


所以有两个RAM的结构图如下,需要注意的是:

(1)16位计数器是一直工作的,所以还是从地址0000开始同时访问两个RAM

(2)当红色箭头1输出的代码(操作码,后面图中说的代码指操作码)是10h也就是Load时,红色箭头2处的选择器的输入应该选左边也就是RAM的输入,因为这是加法的第一个数,不需要进行运算。如果选右边,会被上一次进行的运算结果干扰,上一次的运行结果还在加法器中的右侧输入端

(3)当红色箭头1输出的代码(数据的说明码)是11h也就是Store时,需要将红色箭头3指的数据的RAM的写操作端置1,这样就会把运算的结果写到RAM中


咱们的加法器和锁存器都是8位的,如何进行16位的运算呢,比如76AB + 232C = ?,有一种办法就是先低八位相加存起来,然后再高八位相加。AB + 2C,76 + 23,具体运算如图

当然这是比较好的情况,因为低八位相加没产生进位,如果产生进位了咱们还得处理。回想一下刚开始讲的加法器,两个数相加,产生进位会有一个进位标志,会在下一位运算时加进去,如下图,这是 A +B自己每列相加产生的进位会自己处理,但是咱们这次要做的事,把A + B产生的进位,算到 C + D中去。但是思路是一样的,第一次运算有进位以后,用一个锁存器存起来,锁存器的名字就叫“进位锁存器”吧。下次运算时,把进位锁存器的值连接到进位输入,参与第二次运算。


但是这样把一个16位的数拆成两个8位还是不太灵活。第一,输入数据的流程必须是 输入第一个加数->输入第二个加数->预留出结果位。。。。反复这样,我如果要进行的是32位的数相加,我的结果是分散在四个地方的,查看不方便,第二,我前面运算的结果,在后面的运算中是想用也没法用的

于是就将存放代码(操作码)的RAM优化了一下,之前操作码和数据的对应关系是1对1,现在改为3对1,如下图,第一个代表要操作码,是Load还是Add,还是Store,第二行和第三行代表数据在数据RAM中的地址


这样就灵活了很多,我可以把从计数器还没走到的位置,或者已经走过去的位置进行读写操作,比如进行16位数的加法时,结果可以这样存,如下图,我用左边的代码就可以实现右图表示的将结果保存在相邻的位置


既然RAM是可以随意访问不同位置的数据,并且数据的RAM和操作码的RAM不需要一一对应,咱们就可以用一个RAM了,比如前半部分放操作码,后半部分放数据,完美,这样就出现了下面的结构图,咱们以上图的运算作为讲解例子,(此时需要一个电路,就是心跳一下,红色箭头5指的锁存器clk输入为1,  6、7的 clk为0,第二下,6的为1, 5、7为0,第三下,7为1, 5、6为0。并且第三下之后让2-1选择器的sel取反,让2-1的选择器的输入由红色箭头1变为红色箭头2,然后再下一轮之前再变回来),首先让2-1选择器默认是上端作为输入,计数器第一心跳输出默认是0000,然后从红箭头1出输入到RAM,此时RAM地址0000出存的是10h,所以输出的是10h(操作码Load),此时红色箭头5把10保存下来了,计数器第二下心跳输出默认是0001,然后从红箭头1出输入到RAM,此时RAM地址0001处存的是40h,所以输出的是40h(代表数据的地址),此时红色箭头6把40h保存下来了,计数器第三下心跳输出默认是0002,然后从红箭头1出输入到RAM,此时RAM地址0002处存的是01h,所以输出的是01h(代表数据的地址),此时红色箭头7把40h保存下来了,当心跳第三次结束以后,2-1选择器的输入变为红色箭头2,也就是红色箭头6、7拼起来的16位地址,也就是加数的地址4001h,进入RAM以后,RAM把4001h地址处的数据ABh输出出来,然后进入之前电路图中所示的累加器的锁存器,累加器后面的锁存器的输出,会连接到红色箭头3所示,当遇到11h的操作码时,RAM的w端置1。大体思路就是这样,有些具体的小的结构没体现,可以尝试做一下



是不是已经看得头大了,没事再忍忍,还有最后一次优化就讲完了 ~

咱们再来说说跳转Jump,比如咱们要做乘法,A7h x 1Ch,也就是把A7h重复加1C次,如果单个输入,就太费时间了。如果咱们有跳转,就好了,只写A7h +A7h,执行完再跳到开始处继续执行。咱们的操作码和数据都是放到RAM中的,比如想要跳转到A地址,说白了就是让访问RAM的地址A,那么访问RAM哪的地址,是计数器决定的,所以出发点是,需要的时候修改计数器输出的值,可以通过16位计数器的D型边沿触发器的预置(Pre)和清零(Clr)输入来实现,清零之前有提及,预置的原理一样,就是直接连接线到输出附近


说白了就是,当置位信号(下面会说到这个置位信号)为1时,输入是啥,Q端输出就是啥,所以当遇到跳转指令时,将置位信号变为1,输入端输入跳转指令后面的地址,这样RAM的输入就是跳转指令后面的地址,输出就是RAM中跳转指令后面的地址的值,这样就多了一个跳转指令 Jump(操作码是30h)

所以电路中的计数器,就多了一个置位功能,为了随时改变计数器的值,如下图


现在还有一个问题就是,怎么让跳转指令停下来,我重复1Ch次以后,需要停下来,这样得需要一个停下来的标志位,这个标志位就叫0标志位,他也是个锁存器,我们在加法器上连接上这个锁存器,如图,当加法器输出的每位都是0时,或非门输出是1,也就是零标志位是1


比如重复1C次,想要做的就是,每重复完一次,1C就减1,当时0的时候,上图的加法器就输出0了,然后跳转标志位就变1了,变已以后,咱们就不强制改变计数器的值了,咱们做呢 ~首先,我们可以在强制干预计数器的那个边沿触发器置位那里 “与” 一个取反的0标志位后再输入到置位,0标志位默认是0,取反后是1,所以不干预操作置位,当0标志位是时,置位会失效


如下图这是A7 x 1的运算,左边是数据,右边是操作码和地址


接下来就是怎么在1Ch次后,加法器输出为0(加法器输出为0,零标志位就是1),咱们得在跳转前,专门做一个操作,就是让1C减1,1003h的地址里就是1C,和001E地址的FFH相加,实际上是减1操作了,然后存到1003h,然后重复操作,最后加法器就变成0了(实验一下 1C + FF = 0001 1100 + 1111 1111 =    0001 1011 = 1B) 


最开始讲了加法器,这里讲了RAM(内存)那一个简单的小计算机是不是就出来了,如下图,只需要把需要加的数,依次从开关处输入,没输入完一个按一下“相加”把和存起来,等待下一次相加

用来累加多个数的锁存器称作累加器


现在再来看文章刚开始说的CPU构成的部分如下图,现在就应该很清楚了吧,

寄存器就是锁存器,来存储数据

控制器就是边沿触发器的串联分频产生的,用来产生计数

运算器就是上面说的加法器

时钟就是说的那个铃铛电路



Bug的由来


接下来是自己的一些理解(不保证是对的)


CPU架构

用10h代表Load的意思,用11h代表保存的意思,这个值不是适用于所有的计算机,不同的CPU,可能用不同的值代表、不同的CPU电路的设计也可能不一样,这就延伸出一个知识点,架构

架构是也可以说是指令集架构,是指令集的实现或者可以简单理解成指令集的另一种叫法,arm架构就是指使用arm指令集的处理器。那什么是指令集呢?指令集是存储在CPU内部,对CPU运算进行指导和优化的硬程序,CPU的运行执行的就是指令集,目前市面上的CPU分类主要分有两大阵营,

X86

intel、AMD为首的复杂指令集CPU,Intel、AMD的CPU是X86架构的(Intel早期的处理器名称是以数字来表示,并以“86”作为结尾,包括Intel 8086、80186、80286、80386、80486、80586、奔腾系列等等,因此其架构被称为“x86”)

ARM

IBM、ARM为首的精简指令集CPU。IBM公司的CPU是PowerPC架构,ARM公司是ARM架构

ARM处理器具有低成本、相对的高性能和低耗电的特性,ARM的高性价比和低耗能,非常适用于移动通信领域,所以在移动市场比英特尔更具优势。

那么复杂指令集和精简指令集的区别在哪呢,个人感觉就是咱们今天学习的电路的设计,布局的区别

之前看到一个而比较形象的例子,自己又改造了一下,例如 泡1杯柠檬水

复杂指令集: 1、去泡一杯柠檬水    2、爷,泡好了   (相当于复杂指令里有泡柠檬水这个 "操作码")

精简指令集:1、去泡一杯柠檬水    2、找杯子     3、找柠檬      4、倒上水     5、 放柠檬    6、泡好了。(简洁指令里,没有泡柠檬这个 “操作码”,只能按顺序执行小步)

显然复杂指令速度快效率高,但是如果吩咐去泡杯百香果水,那复杂指令还得有一个泡百香果水的操作码,然后又一堆和之前重复的电路,但是,简介指令,只需要把找柠檬替换成找百香果

X86(复杂指令)性能很牛,电路多并且设计复杂,所以发热量比较大,需要主动散热;一般用于个人电脑、大型服务器等

ARM(精简指令)相对高性能,但是和X86还有些差距,有点就是低功耗,高性价比



单核、多核处理器(个人理解)

什么叫单核什么叫多核,可以简单的理解为1个累加器(也可能是一个运算模块)和多个累加器(运算模块)的区别,为啥会有多核,因为单个累加器的处理能力遇到了瓶颈,也就是没法再快了。为啥没法再快了,我觉得是因为一个时钟心跳需要涉及到好多模块(控制电路、内存、累加器)的配合来完成一条指令的运算,如果时钟频率无限的加快,就会造成配合不好,下一个时钟心跳已经开始,结果上次的运算还没完成,造成运算错误。所以就得有两套电路来进行运算

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,306评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,657评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,928评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,688评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,105评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,024评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,159评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,937评论 0 212
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,689评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,851评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,325评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,651评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,364评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,192评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,985评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,154评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,955评论 2 279

推荐阅读更多精彩内容