# 07 中央处理器 :::tip [前去观看第七集](https://bilibili.com/BV1EW411u7th?p=7) ::: ## 计算机的心脏 —— 中央处理单元,简称「CPU」 ​CPU 负责执行 **程序**,例如 Office,浏览器,游戏《半条命 2》 ​ 程序由一个个操作组成,这些操作叫做**「指令(Instruction)」**,指令用来告诉计算机要做什么。 ## CPU 的组成 中央处理单元 —— CPU,计算机的心脏,由 **ALU**(**算术逻辑单元**)、**寄存器** 和 **RAM**(**随机存取存储器**) 组合在一起。 ## 指令 CPU 负责执行程序,而程序是由 **指令** 组成的,指令负责指示计算机做什么。 打个比方,如果是数学指令(比如加减乘除),CPU 会让 ALU 进行数学计算。如果是内存指令,CPU 会和内存通信,然后读/写值。 ## CPU 的搭建与指令的三个阶段 CPU 有很多的组件,但这次的重点放在功能,而不是线具体怎么连。所以接下来,当我们用一条线连接两个组件的时候,这条线只是必须线路的一个表现形式。 那么,接下来就让我们正式的开始搭建吧。 首先,我们需要一些内存,把上一篇做的 RAM 拿来就可以了。为了保持简单,我们假设它只有 16 个位置,每位置有 8 位。之后再来 4 个 8 位的寄存器 A、B、C、D 用来 **临时存数据** 和 **操作数据**。 我们可以给 CPU 支持的所有指令一个 ID。在下图假设的例子中,我们用前四位存操作码,后四位数据则来自地址或寄存器。所以我们还需要俩个寄存器来完成 CPU.一个寄存器存当前指令的内存地址,叫 **指令地址寄存器**,另一个存当前指令,叫 **指令寄存器**。 ![](%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20221004140939.png) ### 指令的第一个阶段 —— 取指令 当我们启动计算机时,所有的寄存器从 0 开始,为了更好理解,我们过一遍在 RAM 内放的一个程序。 首先,将指令地址寄存器连到 RAM,因为寄存器的值为 0,因此 RAM 返回地址 0 的值,也就是 0010 1110。 0010 1110 被复制到了指令寄存器里。现在,指令拿到了,应该去处理它了,这就是 CPU 的第二个阶段 —— **解码阶段**。 ![](%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20221004142602.png) ### 指令的第二个阶段 —— 解码 指令寄存器中,前 4 位 0010 是 LOAD_A 的指令,意思是把 RAM 的值放入寄存器 A 中。 ![](%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20221004143940.png) 后四位 1110 是 RAM 的地址,转换成十进制是 14. 接下来,指令由**控制单元**来解码。就像之前的所有东西一样,控制单元也是由逻辑门组成(忘记逻辑门是什么的,罚你再去看一遍[第三课](https://book.hyyz.izhai.net/cs/boolean-and-logic-gates/)). 比如,为了识别 LOAD_A 的指令,我们需要一个电路,检查操作码是不是 0010,我们可以用很少的逻辑门来实现。 ![](%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20221004144647.png) 好了,现在已经知道了什么是指令,接下来就让我们开始执行指令。 ### 指令的第三个阶段 —— 执行 用检查是否是 LOAD_A 的电路打开 RAM 的 **允许读取线**,把地址 14 传过去,RAM 拿到了值 0000 0011,也就是十进制 3。因为我们用到的是 LOAD_A 的指令,所以我们只把这个值存在寄存器 A,其他寄存器不受影响,所以我们要用一根线,把 RAM 连到 4 个寄存器,用电路启用寄存器 A 的 **允许写入线**,这样我们就把 RAM 地址 14 的值让在了寄存器 A 中.既然指令完成了,我们可以关掉所有线路,去拿下一个指令了。我们把指令地址寄存器加 1,执行阶段就此结束 ![](%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20221004145957.png) ### 一个小总结 LOAD_A 只是 CPU 可执行的指令中的其中一个,不同的指令有不同的逻辑电路解码,这些逻辑电路会配置 CPU 内的组件来执行对应操作,而具体分析太过繁琐,所以有把控制单元包成一个整体,这样更加简洁。 ![](%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20221004150501.png) ## 第 3 个指令:1000 0100 第 2 个指令与第 1 个指令大同小异,只要按部就班的走就能完成一次循环。但 RAM 的第 3 个指令和第 4 个指令与前两个稍有区别。 第三个指令(ADD)的后 4 位不是 RAM 地址,而是 2 个(数量) 2 位 (单位) 分别代表 2 个寄存器。 第一个地址是 01,代表寄存器 B,第二个是 00,代表寄存器 A,因此,1000 0100 代表着把 B 的值加到 A 里,为了执行,我们用到了 ALU(忘了的,罚你去看[第 5 课](https://book.hyyz.izhai.net/cs/how-computers-calculate-the-alu/))。 在 ADD 指令中,先启用寄存器 B 作为 ALU 的第一个输入,然后 A 做第二个输入。之后,控制单元传递 ADD 操作码告诉 ALU 要做什么。最后的结果应当在寄存器 A 中,但不能直接放入,这回当值新值进入 ALU,不断和自己相加,所以控制单元会用自己的一个寄存器暂时保存结果,关闭 ALU 后再写入正确的寄存器中。当然了,最后还是要把指令地址加一,这样又就完成了一个循环 ![](%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20221004153642.png) ## 最后一个指令:0100 1101 这个指令是 STORE_A 指令(把寄存器 A 的值放入内存),它的后四位是 RAM 地址,但要做的不是允许读取,而是允许写入,同时打开寄存器 A 的允许读取,将 A 的值纯给 RAM。 至此,我们运行了第一个电脑程序,恭喜! ## 时钟 **时钟**,是负责管理 CPU 节奏的,它以一定的间隔发电信号,控制单元会用这个信号推进 CPU 的内部操作。当然了,节奏不能太快,因为就算是电也要一定时间来传输。 ## 时钟速度 每一次指令走完三个阶段的速度叫**时钟速度**,单位是赫兹,表示频率的单位,一赫兹代表一秒一个周期。如今的处理器已经达到了几千兆赫兹。 ## 超频 超频即使修改时钟速度,加快 CPU 的速度,但注意,超频太多会让 CPU 过热或产生乱码,因为信号跟不上时钟。 ## 降频 当然了,既然有超频,自然有降频。降频一般用在跑新能要求较低的程序或者人已经离开时,降频能够更加省电。 为了尽可能省电,现在的处理器可以按需求加快或减慢时钟速度,这叫做动态调整频率 最后,让我们把时钟加入到我们组成的 CPU 中,这样我们的 CPU 就完整啦!现在可以放到盒子里,拿出去和你的朋友大肆炫耀了! ## 接下来 下一课,我们要加强 CPU,给它拓展更多的指令,同时开始讲软件。