昨晚在回顾之前所写的问答时,我发现一篇关于“CPU是怎么认识代码”的问题热度很高,很多朋友表示看了我写依旧云里雾里,不得要领。原因在于我主要讲的是编译器的作用和CPU的工作模式,没有涉及到更加底层的知识。大家的疑惑主要集中在一点:我们都清楚CPU只认识0和1,但CPU到底是如何认识0和1的呢?
机器是没有思想的,只会安装规定好的电路工作
我们在学习单片机的时候,都会将写好的程序烧录进CPU里。那么各位有没有想过,这个过程为什么要叫“烧录”?
原因就是它是真的在烧:一块芯片的内部是密密麻麻,呈矩阵排列的熔丝。当我们写好程序后,程序经过编译器转换成二进制代码(0或1),再通过烧录器的大量流烧断熔丝,将这些二进制代码写进空白的芯片。程序中的0表示这条熔丝要烧断,1表示这条熔丝不烧,以此方法记录二进制信息。程序烧录好后,芯片就有了逻辑功能。
简单来讲,烧录就是规定好了电路,用户只需给CPU通电就行,它就可以按照事先规定好的电路得出结果。从用户的角度来看,好像是计算机读懂了我们写的程序,但实际上它就是循规蹈矩,这点和我们去开灯关灯没什么区别,只是通断更多,电路状态更加复杂。
下图是一张早期的只读存储器PROM,由于它在烧录后熔丝无法恢复,所以只能用来存储特定的程序,所以也被叫做一次性存储器。
现在这种熔丝设计的存储器基本上被淘汰了,取而代之的是可以反复擦写的EPROM,在结构上是这样的:
我们会发现,EPROM的并没有采用熔丝设计,而是一种像沟壑的东西,这其实是现代数字电路的基础——场效应管。在具体介绍场效应管前,我们先来了解一下计算机的发展和集成电路。
计算机发展史和数字电路
从1946年第一台真正意义上的电子计算机ENIAC面世至今,计算机的硬件技术已经发展到了第四代。
第一代电子管计算机:逻辑元件采用真空电子管,体积大,可靠性差,成本高昂,为日后计算机的发展奠定了基础;
第二代晶体管计算机:逻辑元件采用晶体管,电子线路的结构得以优化改善,大大提高了计算机使用寿命,减小功耗;
第三代集成电路数字机:逻辑元件采用中小型规模的集成电路板,速度大幅提高,性能更强,计算机正式迈入图像和文字处理;
第四代大规模集成电路:逻辑元件采用大规模和超大规模的集成电路,性能巨幅提升,成本降低,计算机开始走进千家万户,也是当下我们主要使用的计算机类型。
根据功能和结构的不同,集成电路可以分成三种:模拟电路,数字电路,数/模混合电路。由于模拟电路不稳定,且抗干扰能力较差,而数/模混合还不太成熟,目前我们主要使用的集成电路板都是由数字电路搭建的。
所谓数字电路,就是用数学信号完成对数字量进程数值运算和逻辑运算的电路,其基本电学原理,都与模拟电路相同。在理解了什么是数字电路后,我们再来看场效应管。
场效应管简称为MOS,是一类金属-氧化物构成的半导体。蓝色部分是场效应管的主体部分,平时处于是绝缘的,此时源级(Source)和漏级(Drain)的电流不能从中间流过。当栅极(Gate)有电压时,一部分蓝色区域变成导体,源级和漏级就被打通了。
于是我们只要通过是否给栅极电压,就能实现电路导通与否,就好比我们去开关灯一样。需要注意的是,场效应管看上去和模拟电路中的PN结二极管有些类似,都是实现对电流的控制,但两者有着本质的区别:场效应管是电压控制元件,二极管是电流控制元件,MOS不会出现击穿情况,在安全性上要比二极管高得多。
在理解了什么是烧录和MOS的作用后,我们就可以设计电路,来实现算数与逻辑的运算了。
布尔运算,二进制和门电路
1845年,英国一位名不见经传的数学家乔治·布尔在礼拜时心血来潮,认为哲学问题可以用数学来表示。他将自己的想法编成书,即《逻辑的数学分析》和《思维规律的研究》,详细阐述了如何将逻辑问题转换成数学公式。
布尔代数中只有两个值:1和0;三种运算:逻辑加、逻辑乘和逻辑非。这里的1和0并不是数字意义上的1和0,而是一个事物的两种矛盾状态。比如一个人,活着就是1,死了就是0。
虽然乔治·布尔的想法很有创新意义,但在当时并不受重视,甚至一度被认为是伪科学。直到乔治·布尔去世多年后,另一位计算机先驱人物,密码学的奠基人香农发现了这份被世人遗忘的宝藏。1938年,香农在《继电器与开关电路的符号分析》中,将布尔代数与开关电路联系起来,凭借该文章,年仅22岁的香农成功取得了麻省理工电气工程硕士学位。
人们可以依靠继电器构成逻辑门电路,从而逻辑上的运算结果:
与门:当两个输入端 A、 B同时为“1”时, 输出端 C 才为“1” , 否则为“0”;
或门:当两个输入端 A、 B 中, 只要至少有一个输入端为“1”时, 输出 端 C 就为“1
非”门:输出状态总和输入状态相反。
从这三种基本的门电路,可以构成与非,异或等其他门电路,它们的符号和结构如下图所示:
有了门电路,人类制造出了第一款电子管计算机。在设计之初,科学家们还是沿用了人类的思维采用了十进制,用十个真空管代表一位上的0~9,看起来是很方便,但一个真空管对应一位数实在是太浪费了,计算机的体积也非常大。此时另一位不世出的天才科学家又站了出来,他就是被誉为“现代计算机之父”的冯诺依曼。
冯诺依曼提出将CPU改为了二进制,二进制的好处在于它刚好与高低电平相对应,他规定1代表高电平,0代表低电平;除此之外,二进制还有一个优势就是精度够高,举个例子,0~5V分成10份,电压每变化0.5V就代表十进制0~9中的一个值,当时电子元件的远不如现在这般精密,一旦出现误判后果是非常严重的。得益于这两点,二进制的设计一直被沿用至今。
自己设计一款CPU
严格来讲,CPU只是芯片的一部分,不过目前我们习惯性的将这两个概念混在一起了。CPU全称为中央处理器,由控制单元,运算单元和存储单元三部分组成。这里我们单以运算器为例,来讲一下如何用逻辑门来实现数的运算
运算单元的类型有很多,加法器是最基础的一种,其余三种运算都能用加法来实现。
在不考虑进位情况下,根据布尔代数的定义,我们可以得到加法的真值表:
其中A,B为输入,C为进位,S为输出值,这种加法器叫做半加器,其布尔式为A⊕B=A B+ AB当需要考虑进位时,输入变成了三位数,根据布尔代数的定义,全加器需要多一个进位输入,所以需要使用两个半加器,将一个半加器的加和输出连接到另一个半加器,这样一来,就可以用来进位了。我们可以列出真值表,其布尔式如下:
(A⊕B)⊕C=A⊕B⊕C,由于排版原因,此处不再展开。
门电路图如下,
当设计完全加器后,我们搭建二进制加法器了。以一个八位二进制加法器为例,则需使用八个全加器,2^8=256,所以该加法器可以进行0~255以内的加法运算,每一个全加器的进位输入与上一个全加器的进位输出相连。
因为减法可以看做是加负数(计算机通常采用“取反补1”),乘法看作是多个数相加,除法看作为次数是被除数的减法运算,所以我们便完成了运算器的设计。
无论是存储器(存储器中的0和1按照特定排序,构成不同的信息),运算器,还是控制器,他们在原理上都是一致的,都是根据布尔式推出的真值来设计出相应的门电路。所以大家现在可以理解,为什么CPU会卖的那么贵,在一块小小的CPU上集成这么多复杂的元件真的不是一件容易事。
简单来讲,一段代码会先被编译器翻译,变成0和1的排列,他们对应着的高低电平,根据电平的不同走不同的逻辑电路。我们只是从键盘上敲了几行代码,计算机就要做大量的运算工作。
所以将计算机评选为人类历史上文明程度最高的产物,真不是空穴来风。