这个问题从高中就开始疑惑,计算机究竟是如何理解人类思维,如何进行计算?我很想知道最最基本的工作原理,但是大学里好多课程,数字逻辑,计算机组成原理,只是从不同层次上解释了计算机的工作原理,很可惜的是,我并没有把知识穿起来。看了很多人的回答,大家也只是解释了一部分问题,没有完整的把计算机整个的抽象层次说清楚。在大学里我看到了 Charles Petzold的《编码 隐匿在计算机软硬件背后的语言》,这部永不退色的计算机经典著作,为了讲明白了这件事儿,今天我决定用自己简略的话,回顾一下作者写作的思路,用我的理解为大家讲述计算机的工作原理。希望我能够完成。
今天的计算机已经变得相当复杂,是有史以来人类创造的最复杂最精密的仪器,没有之一,是二十世纪技术领域的“登峰造极之作”,计算机与生俱来的层次化体系结构,掩盖了技术背后最本质的东西,现在已经很少有人去关心计算机最本质的工作原理,我希望能剖析计算机一层层‘“抽象”面纱,展现最本质的“计算”过程。基本的知识基础是高中物理,高中数学。
第一节 计算器
下面回到高中课堂,我依稀记得在电磁学那一部分,讲到了电磁继电器,当时老师说,继电器是很重要的发明,我打开物理课本,“什么破东西嘛”,太简单了,那时候觉得像继电器这样的发明没什么用。高中数学中也讲到,布尔代数,简单老说就是,与、或、非,而且教科书上说,布尔代数意义重大云云。下面问题来了,我只用继电器能不是实现简单的计算器?注意是“计算器”,而不是计算机,答案是肯定的,来,那就看看,如何用继电器打造出一个”计算器“,进而打造出一台”计算机“
<img src="https://pic4.zhimg.com/50/1fc0540c5f07d5eebb68575ca70e2756_hd.jpg" data-rawwidth="991" data-rawheight="422" class="origin_image zh-lightbox-thumb" width="991" data-original="https://pic4.zhimg.com/1fc0540c5f07d5eebb68575ca70e2756_r.jpg">两个继电器串联,点亮一盏灯,这算不算实现了“与”的操作呢?两“真”为”真“
<img src="https://pic1.zhimg.com/50/5d53b4b54c655ee27b1e430136d5498c_hd.jpg" data-rawwidth="1018" data-rawheight="490" class="origin_image zh-lightbox-thumb" width="1018" data-original="https://pic1.zhimg.com/5d53b4b54c655ee27b1e430136d5498c_r.jpg">两个继电器并联,点亮一盏灯,是不是实现了”或“的操作?一真为真
<img src="https://pic3.zhimg.com/50/0c6a6c0b33ad91d0c399d55fd662da97_hd.jpg" data-rawwidth="1081" data-rawheight="413" class="origin_image zh-lightbox-thumb" width="1081" data-original="https://pic3.zhimg.com/0c6a6c0b33ad91d0c399d55fd662da97_r.jpg">一个继电器本身就可以实现”非“的操作
这样一来,物理上的继电器,和布尔代数,完美的融合起来,我把与或非门继电器实现称作”物理层“,每张图右边的符号表示,称作”布尔逻辑层“,从”物理层“到”布尔逻辑层“是我们的第一层抽象,很简单吧?(当然现代计算器从物理实现到逻辑实现,已经不再使用继电器,而是在硅芯片上雕刻一个个的晶体管,但晶体管的数量绝对不会减少,这一点@丁旭 已经说得很明白)
接下来可能有人问,你整这些小儿科的东西,有什么用呢?别急,看我慢慢展开!
我们知道,布尔代数是一种数学,既然是在一种数学,那么存在数学运算啊,数学运算能用继电器实现吗,of course
<img src="https://pic4.zhimg.com/50/df0c9b68c81ac1122840e69ddbc64bae_hd.jpg" data-rawwidth="1245" data-rawheight="582" class="origin_image zh-lightbox-thumb" width="1245" data-original="https://pic4.zhimg.com/df0c9b68c81ac1122840e69ddbc64bae_r.jpg">一个或门,一个与非门,一个与门,按照图示连在一起形成了一个最常见的运算,异或运算,”相同为假,不同为真“,那物理实现上怎么做呢?请在大脑中想想怎么连线,一共七个继电器就可以实现,有了异或运算,我们就可以实现更复杂的运算,下面就和我们实现一台”计算器“直接相关了
<img src="https://pic1.zhimg.com/50/f895be5fdc8725ffc9f188eac4beef38_hd.jpg" data-rawwidth="976" data-rawheight="564" class="origin_image zh-lightbox-thumb" width="976" data-original="https://pic1.zhimg.com/f895be5fdc8725ffc9f188eac4beef38_r.jpg">一个异或门和一个与门,形成一个”半加器“,图示下边的符号表示一个半加器,这里是新一层的抽象,从布尔逻辑运算到”计算器件“的抽象
<img src="https://pic2.zhimg.com/50/698a1a781324d261ae7a4e46bab7f75b_hd.jpg" data-rawwidth="1202" data-rawheight="577" class="origin_image zh-lightbox-thumb" width="1202" data-original="https://pic2.zhimg.com/698a1a781324d261ae7a4e46bab7f75b_r.jpg">有一个半加器,距离我们实现手工打造一个”计算机“还很远,然而两个半加器,一个或门,可以实现一个”全加器“,为什么叫全加器呢?因为我们使用它可以实现一位加法的计算!(这里是二进制,问题的题目,为什么计算机能读懂”0“和”1“,看到这里是不是心头一喜呢?)
<img src="https://pic4.zhimg.com/50/b0e15c8c39e3395716d600568027e8c1_hd.jpg" data-rawwidth="1097" data-rawheight="601" class="origin_image zh-lightbox-thumb" width="1097" data-original="https://pic4.zhimg.com/b0e15c8c39e3395716d600568027e8c1_r.jpg">有了一位”全加器“,我们实现8位加法的计算还远吗?当然不远,8个全加器,按图示相连,就可以实现8位加法计算(和我们在纸上进行加法运算很像,进位的操作很显然。当然,这里都是进行二进制加法),右下方是8位加法器的表示方式。
要是这会儿在19世纪,在电力革命的年代,我一定要亲手打造一个计算器!
<img src="https://pic2.zhimg.com/50/abcf1616b6be0b25ca278b6e76fd1be5_hd.jpg" data-rawwidth="1164" data-rawheight="555" class="origin_image zh-lightbox-thumb" width="1164" data-original="https://pic2.zhimg.com/abcf1616b6be0b25ca278b6e76fd1be5_r.jpg">画的比较简陋,见过卡车上的按钮吗?上下拨动的那种,这是我穿越回19世纪站在专利局门口,阐述我”伟大”的发明,“我发明的计算器,有两排输入按钮,每个按钮上下拨动表示输入的是0或者1,最下排是9个灯泡,灯泡的亮与灭,指示这一位是0,还是1,我的发明是划时代的,可以把人类从繁杂的计算过程中解救出来...”
“什么?就因为我的计算器不能实现减法运算儿拒绝我的专利申请,减法运算?减法运算,怎样实现计算机的减法运算呢?”
计算机发展过程中,最重要的思想是“抽象”,一层层的抽象封装了实现的细节,使的计算机开发人员更关注与逻辑的实现,相信有了我上面的表述,读者应该能看懂下边的抽象思想:
<img src="https://pic4.zhimg.com/50/c48d5ad5b23a47402bddfd269bd073a4_hd.jpg" data-rawwidth="700" data-rawheight="236" class="origin_image zh-lightbox-thumb" width="700" data-original="https://pic4.zhimg.com/c48d5ad5b23a47402bddfd269bd073a4_r.jpg">这个电路实现了把输入的数据取反(0->1,1->0)
<img src="https://pic1.zhimg.com/50/efa7a48f599592511e7f632c3bbdc403_hd.jpg" data-rawwidth="546" data-rawheight="228" class="origin_image zh-lightbox-thumb" width="546" data-original="https://pic1.zhimg.com/efa7a48f599592511e7f632c3bbdc403_r.jpg">这是求补器的“抽象”
减法的逻辑实现我直接给出,相信读者也应该能看明白
<img src="https://pic4.zhimg.com/50/4b9152b553157da23f057aa9c2306872_hd.jpg" data-rawwidth="669" data-rawheight="442" class="origin_image zh-lightbox-thumb" width="669" data-original="https://pic4.zhimg.com/4b9152b553157da23f057aa9c2306872_r.jpg">我还清楚的记得,在计算机组成这门课上,老师讲述,原码和补码概念,“在计算机内部,正数的补码是它本身,负数的补码,记得取反加1“,为什么取反加1呢?看看上边的实现,计算机内部如何实现减法?有个取反操作,还有个进位操作,这不正是”取反加1“吗?
下面从逻辑实现层,回到物理层,思考下,需要多少继电器才能实现这样的 ”小发明“,算了,吓一跳吧?然而我们的计算机先驱康拉德·楚泽花费了十年心学,3000多个继电器才早出一个计算机原型,所以,,,本着向先哲致敬的精神,让我们在大脑中”打造出“一台计算机
<img src="https://pic1.zhimg.com/50/75447866082deb93fdac708c02304401_hd.jpg" data-rawwidth="686" data-rawheight="283" class="origin_image zh-lightbox-thumb" width="686" data-original="https://pic1.zhimg.com/75447866082deb93fdac708c02304401_r.jpg">”我的专利不仅仅能实现加法操作,也能实现减法操作,计算具有普遍性,具有划时代的意义,可以把人类从复杂的计算中解救而出来...“
至此,我们实现了一个简单的计算器实现,不难吧?然而这才只是万里长征的第一步。
接下来我来说说,计算机是如何存储信息的,这真是个费力活儿,在不太遥远的过去,二十年前,计算机的存储量还非常有限,我记得初中那会儿还没有MP3,用磁带听歌,直到最近,存储技术才有了长足的进步,当然这是后话。
第二节,计数器
人类的感官,听觉,触觉,味觉,视觉,感官器官接受外界的刺激,在大脑中留下神经信号,进而形成对“外部世界”的认识,那抽象的事物怎么去认识呢?
电灯通电点亮灯泡,高中的物理知识解释,足够了。电可以让物体运动,这个道理人人都懂。坐在回家的高铁上,让我想想一下高速列车是如何运动的:驾驶员按下通电按钮,带动电车引擎,电车引擎通过传动装置把牵引力传给电车车轮,列车得以启动。高速列车的动力系统也相当复杂,我不了解每一个实现的细节,但是我可以想想出电车引擎的工作原理,为什么?因为这些都是实实在在的实物,看得见摸得着。那我想想出计算机的工作原理吗?答案是不能,为什么?因为计算机一层层的“抽象”,一个小小的物理器件上集成了上亿的基本元器件,使计算机真正的工作原理是我们越来越遥远。
下面还让我们回到19世纪末,二十世纪初,那个激荡人心的电力革命的年代,让我们去还原真实的技术实现过程。回到高中物理课堂
我们已经讲解了如何去制造一个一台简易的“计算器”,不知不觉下课了,这时我听到一阵刺耳的下课铃声。电铃和计算机有关系吗?我直接上图吧
<img src="https://pic4.zhimg.com/50/61105d437b8c7907fc082ca91298634b_hd.jpg" data-rawwidth="500" data-rawheight="500" class="origin_image zh-lightbox-thumb" width="500" data-original="https://pic4.zhimg.com/61105d437b8c7907fc082ca91298634b_r.jpg">注意看旁边的那个金属小锤子
<img src="https://pic1.zhimg.com/50/efbc42bb94d00e4ae7551b7e00780eb5_hd.jpg" data-rawwidth="570" data-rawheight="324" class="origin_image zh-lightbox-thumb" width="570" data-original="https://pic1.zhimg.com/efbc42bb94d00e4ae7551b7e00780eb5_r.jpg">电铃的工作原理如上图所示,大家想象下,电铃的小锤子震荡起来敲打金属盖发出声音的情形,duang,duang,daung,形象吧?(这种电路叫做震荡器)
<img src="https://pic1.zhimg.com/50/43689534f8a324e541ffe65a6faf82b2_hd.jpg" data-rawwidth="513" data-rawheight="168" class="origin_image zh-lightbox-thumb" width="513" data-original="https://pic1.zhimg.com/43689534f8a324e541ffe65a6faf82b2_r.jpg">振荡器是不是可以实现计数功能呢?交替的输出0和1,哈哈,感叹造物的神奇吧!
下面我们再来看一些神奇的电路,当初的先驱们是怎么想到这些复杂而精致的设计
<img src="https://pic4.zhimg.com/50/b6e75df9b37db978235fc44d5afaa343_hd.jpg" data-rawwidth="614" data-rawheight="216" class="origin_image zh-lightbox-thumb" width="614" data-original="https://pic4.zhimg.com/b6e75df9b37db978235fc44d5afaa343_r.jpg">闭上上方的电路,灯亮了
<img src="https://pic3.zhimg.com/50/4062212aa930d6a50c628f05d316bf3c_hd.jpg" data-rawwidth="582" data-rawheight="225" class="origin_image zh-lightbox-thumb" width="582" data-original="https://pic3.zhimg.com/4062212aa930d6a50c628f05d316bf3c_r.jpg">断开上方的电路,灯依然在亮
<img src="https://pic1.zhimg.com/50/35e969d3c178a380f62b5cb8f6375270_hd.jpg" data-rawwidth="499" data-rawheight="199" class="origin_image zh-lightbox-thumb" width="499" data-original="https://pic1.zhimg.com/35e969d3c178a380f62b5cb8f6375270_r.jpg">闭合下方电路,灯灭了
<img src="https://pic2.zhimg.com/50/92b6e7737148a2a833630d7f9db307a7_hd.jpg" data-rawwidth="488" data-rawheight="187" class="origin_image zh-lightbox-thumb" width="488" data-original="https://pic2.zhimg.com/92b6e7737148a2a833630d7f9db307a7_r.jpg">断开下方的电路,灯依然不亮
电路的奇特之处在于:同样是在开关都断开的状态下,灯泡有时候亮,有时候不亮,当开关都断开时,电路有两个稳定状态,这类电路叫做“ 触发器”。(英国物理学家1918在工作中发现的)
触发器电路可以保持信息,确切的说,可以“记忆”某些信息,他可以“记忆”那个开关先闭合。触发器是一个大家族,大家要是有兴趣可以去看相关资料。请记住一点!触发器是用来“记忆”信息的,我再给出两类常用的触发器
<img src="https://pic4.zhimg.com/50/331750ce438f1fa6ece5722c7d963a31_hd.jpg" data-rawwidth="517" data-rawheight="247" class="origin_image zh-lightbox-thumb" width="517" data-original="https://pic4.zhimg.com/331750ce438f1fa6ece5722c7d963a31_r.jpg">这个叫做“D型触发器”,具体实现如上图,我们的表示一直都停留在很“底层”,一直都很关注实现的细节,随着细节实现越来越多,我们需要上升到高一层的层次,更加关注功能的实现,而不是陷于细节实现的泥潭!(想一想,为什么说,计算机具有与生俱来的层次结构)
数据端简写为D,时钟端简写为Clk,功能表如下:
<img src="https://pic3.zhimg.com/50/eb33d69de15ff30f3405ae2d7cda3b0d_hd.jpg" data-rawwidth="248" data-rawheight="194" class="content_image" width="248">脑袋里想象下,触发器是一个很听话的孩子,当clk端通电时,相当于告诉孩子,“孩子啊,你要记住我传给的信息”,clk断电时,孩子在自由自在的玩耍,完全不接受任何传过来的指令,很形象,不是吗?
在D型触发器的基础上实现了更复杂的功能,“ 边缘触发的D型触发器”
<img src="https://pic1.zhimg.com/50/c935dbb047ae91a8ddd145011eeb7dee_hd.jpg" data-rawwidth="587" data-rawheight="242" class="origin_image zh-lightbox-thumb" width="587" data-original="https://pic1.zhimg.com/c935dbb047ae91a8ddd145011eeb7dee_r.jpg">“抽象”图
<img src="https://pic4.zhimg.com/50/04533d2e1e81dfa82358c30247f7af19_hd.jpg" data-rawwidth="156" data-rawheight="91" class="content_image" width="156">again,抽象的思想,使我们脱离的细节实现(上图),更加关注功能
<img src="https://pic2.zhimg.com/50/6f72ff93401485845b9fce471663e998_hd.jpg" data-rawwidth="220" data-rawheight="145" class="content_image" width="220">向上的箭头,表示电信号从0到1变化的那一瞬间有效,再次在脑袋里想象下,触发器是一个很听话的孩子,当clk从0->1变化时,相当于告诉孩子,“孩子啊,赶紧接住我给你的球,球在这里指信息”,其他状态下,孩子在自由自在的玩耍,完全不接受任何传过来的指令。
有人问,说了这么多,到底想干什么?好的,告诉你,用这些可以实现一个计数器,记得小孩子学数数吗?我们要做的的就是要用机器来从0开始数数,真的吗?恩,离这一步已经很近了,不信看下边
<img src="https://pic2.zhimg.com/50/fd8fa89f2ff60f7515cc5893bff7ba9f_hd.jpg" data-rawwidth="369" data-rawheight="156" class="content_image" width="369">简单的,把振荡器和触发器相连
<img src="https://pic3.zhimg.com/50/232f79df6e2e612d67f3bc2bd779dafc_hd.jpg" data-rawwidth="518" data-rawheight="188" class="origin_image zh-lightbox-thumb" width="518" data-original="https://pic3.zhimg.com/232f79df6e2e612d67f3bc2bd779dafc_r.jpg">电平信号的变化
稍微扩展一下,实现更复杂的功能,应该能看明白吧
<img src="https://pic2.zhimg.com/50/65c84dbb7a2ad9ca691aff8494b9b587_hd.jpg" data-rawwidth="528" data-rawheight="179" class="origin_image zh-lightbox-thumb" width="528" data-original="https://pic2.zhimg.com/65c84dbb7a2ad9ca691aff8494b9b587_r.jpg">电平信号的变化(标上0和1)
<img src="https://pic4.zhimg.com/50/99066d4b5cb7db76c286e58255672644_hd.jpg" data-rawwidth="594" data-rawheight="253" class="origin_image zh-lightbox-thumb" width="594" data-original="https://pic4.zhimg.com/99066d4b5cb7db76c286e58255672644_r.jpg">嗨嗨,清醒下,我们得到了什么?把上图顺时针旋转90度,你发现了吗
<img src="https://pic3.zhimg.com/50/ae382b0ce95c316b8ee811980d69b4e2_hd.jpg" data-rawwidth="354" data-rawheight="461" class="content_image" width="354">这不就是在计数吗?用二进制的方式计数!
把8个触发器连接在一起,然后放入一个盒子里,构成了一个8位计数器,能从0数数到2^8-1,(0-255),这个计数器称为“8位行波计数器”
<img src="https://pic3.zhimg.com/50/d8731896e52c98108fc9135065beb4ba_hd.jpg" data-rawwidth="477" data-rawheight="167" class="origin_image zh-lightbox-thumb" width="477" data-original="https://pic3.zhimg.com/d8731896e52c98108fc9135065beb4ba_r.jpg">现在,我们已经懂得如何继电器来做加法、减法、计数了,这一件很有成就感的事儿,使用的技术也是100多年前就存在的技术。
第三节 存储器
我想用继电器打造一个存储量为64K x 8的存储阵列,我能实现吗?这会儿可是在二十世纪初!如果我穿越回那个年代,一定会再次为我的“发明”申请专利,如果真是这样,那计算机的发展史上会留下我的名字(呵呵,意淫一下),下面就看看我是如何实现我的“发明”吧
上节,我已经提到,触发器可以“记忆”1位的信息
<img src="https://pic1.zhimg.com/50/9833ff487aa16bb2ce862a99723af1bb_hd.jpg" data-rawwidth="563" data-rawheight="244" class="origin_image zh-lightbox-thumb" width="563" data-original="https://pic1.zhimg.com/9833ff487aa16bb2ce862a99723af1bb_r.jpg">就是上图这个样子,我们把它抽象成:
<img src="https://pic3.zhimg.com/50/49416d79c4556296808e73277b631ab0_hd.jpg" data-rawwidth="227" data-rawheight="137" class="content_image" width="227">我们把上图称作“1位锁存器”,想一想,两个输入线和一个输出线都是什么意思,我上节已经解释过,来、来、来,想一想那个淘气的小朋友。
有了“1”,那么距离“100000”还会远吗?无非就是如何组织n个“1”,“抽象”的量级提升的过程
<img src="https://pic4.zhimg.com/50/fdb0e71298af7f53f4265cd1c601337c_hd.jpg" data-rawwidth="736" data-rawheight="337" class="origin_image zh-lightbox-thumb" width="736" data-original="https://pic4.zhimg.com/fdb0e71298af7f53f4265cd1c601337c_r.jpg">这是8位锁存器
<img src="https://pic2.zhimg.com/50/e6001e7cee4fee19efb3f0e93b29c4bf_hd.jpg" data-rawwidth="490" data-rawheight="153" class="origin_image zh-lightbox-thumb" width="490" data-original="https://pic2.zhimg.com/e6001e7cee4fee19efb3f0e93b29c4bf_r.jpg">简写成这种形式
再来看两个神奇的发明,或许你也会为发明者神奇的构思所折服
<img src="https://pic3.zhimg.com/50/a1b5b1067aff3bb66f5e7c4e44e41664_hd.jpg" data-rawwidth="590" data-rawheight="253" class="origin_image zh-lightbox-thumb" width="590" data-original="https://pic3.zhimg.com/a1b5b1067aff3bb66f5e7c4e44e41664_r.jpg">我想制作出这么一个元器件,他要实现这些功能。想想一下,某一天,你成了一个名人,每天前来拜访的人络绎不绝,今天呢,来了八个人,但是你时间有限,只能见一个人,那就让5号来吧(把拜访者编号,0-7),5号拜访者带来了自己的礼物(0或者1的信息)。看图,左边的三根线表示拜访者的地址(当然是二进制编码),000,001,010,011,100,101,110,111,5号就是101,这时候呢,我只需要把S0和S2通电,那么5号拜访者就进来了,献上自己的礼物(1位的信息)。
怎么实现这个功能呢?有兴趣的自己去研究下面实现,请记住,我们现在讨论的内容抽象的层次已经不是最最底层的实现了,而是更加关注于逻辑器件实现的功能
<img src="https://pic1.zhimg.com/50/5ce1334ec94cbd23fe8d2d239c75b87f_hd.jpg" data-rawwidth="578" data-rawheight="463" class="origin_image zh-lightbox-thumb" width="578" data-original="https://pic1.zhimg.com/5ce1334ec94cbd23fe8d2d239c75b87f_r.jpg">这叫“8-1选择器”
反过来,我有一封信需要送出去,这封信的内容是0或者1,现在我也有8个快递小哥可以选择,编号分别是000,001,010,011,100,101,110,111,我让谁去给我送信呢?那就还是5号吧,于是我把地址分别设置为101,5号小哥就去给我送信了,给出具体实现,有兴趣的自己去看吧
<img src="https://pic1.zhimg.com/50/c415fae875bae2918b3bddb7f29ffef7_hd.jpg" data-rawwidth="437" data-rawheight="504" class="origin_image zh-lightbox-thumb" width="437" data-original="https://pic1.zhimg.com/c415fae875bae2918b3bddb7f29ffef7_r.jpg">这个电路名儿叫做“3-8译码器”
有了8-1选择器和3-8译码器,就可以制作出一个8位存储器了
<img src="https://pic1.zhimg.com/50/f62f1d4cbbe509c9c738fd1d5425468d_hd.jpg" data-rawwidth="674" data-rawheight="488" class="origin_image zh-lightbox-thumb" width="674" data-original="https://pic1.zhimg.com/f62f1d4cbbe509c9c738fd1d5425468d_r.jpg">again,把复杂的电路实现,抽象成简单的符号表示
<img src="https://pic3.zhimg.com/50/fd0390995d3b7f0066a49de6d3c8fab7_hd.jpg" data-rawwidth="430" data-rawheight="171" class="origin_image zh-lightbox-thumb" width="430" data-original="https://pic3.zhimg.com/fd0390995d3b7f0066a49de6d3c8fab7_r.jpg">读/写存储器,通常叫做随机访问存储器或者叫RAM,RAM可存储8个单独的1位数据
如何得到16 X 1的RAM呢?相信大家都能想到,用2个 8 X 1的RAM,我仿佛回到了《计算机组成》的课堂,让我再来做一次作业吧
<img src="https://pic2.zhimg.com/50/bfb5aec48893487c50feee07b5be62ee_hd.jpg" data-rawwidth="530" data-rawheight="357" class="origin_image zh-lightbox-thumb" width="530" data-original="https://pic2.zhimg.com/bfb5aec48893487c50feee07b5be62ee_r.jpg">简写如下:
<img src="https://pic2.zhimg.com/50/733d785f5c7131b1860d8e80d346472d_hd.jpg" data-rawwidth="446" data-rawheight="196" class="origin_image zh-lightbox-thumb" width="446" data-original="https://pic2.zhimg.com/733d785f5c7131b1860d8e80d346472d_r.jpg">这种方式或许正确,但是使用了三根地址线,两根数据线,能不能使用4根地址线1根数据线呢?
加一个2-1选择器不就行了吗?(设计一个2-1选择器,这会儿应该不算什么难事儿)
<img src="https://pic4.zhimg.com/50/5b389368380349bad23c2d954426ffaa_hd.jpg" data-rawwidth="557" data-rawheight="539" class="origin_image zh-lightbox-thumb" width="557" data-original="https://pic4.zhimg.com/5b389368380349bad23c2d954426ffaa_r.jpg">再次用符号简写:
<img src="https://pic4.zhimg.com/50/15f7d75b93ab9fd1a53b56f586386889_hd.jpg" data-rawwidth="461" data-rawheight="198" class="origin_image zh-lightbox-thumb" width="461" data-original="https://pic4.zhimg.com/15f7d75b93ab9fd1a53b56f586386889_r.jpg">回到我们的出发点,怎么得到64K X 8的存储阵列呢?
无非就是努力提高8位锁存器的集成程度嘛,我可以想象,读者看到这里,脑子里全是密密麻麻的的连线,或许你还一时想象不到连线的方式,但是看到这里,64K X 8的存储阵列一定能用某种方式实现,对吧?虽然没有实现其电路图,但我也可以说,我理解了存储器工作原理,(你懂了吗?)。
<img src="https://pic1.zhimg.com/50/1b19ffd075754b9c0c3d5fa8bfef0230_hd.jpg" data-rawwidth="544" data-rawheight="188" class="origin_image zh-lightbox-thumb" width="544" data-original="https://pic1.zhimg.com/1b19ffd075754b9c0c3d5fa8bfef0230_r.jpg">1024 X 8RAM的符号表示,2的16次方,即64K,地址线有16根,数据线有8根
为了申请我的专利,我需要做出一个机器的外部壳子,和第一节中的“计算器”一样,把这个机器的壳子把我所有实现的过程封装起来,形成一个“黑盒”,只保留几个外部的接口(也就是那几根数据线,一定要记得他们的功能),我要做成的外部盒子是这个样子
<img src="https://pic4.zhimg.com/50/490b053886294f7543b31941a5d2d0d0_hd.jpg" data-rawwidth="626" data-rawheight="260" class="origin_image zh-lightbox-thumb" width="626" data-original="https://pic4.zhimg.com/490b053886294f7543b31941a5d2d0d0_r.jpg">上一排的对应16根数据线,下一排有8根数据线,这个不用解释,相信把上文看完的都能明白什么意思,takeover这个按钮表示是否使得当前控制面板处于“激活状态”,也就是说,这个开关的作用是确定由控制面板还是又外部所连接的其他电路(从来没说过,没有连接外部其他电路,或者想象下,我这个机器壳子外面有一排的针孔,外部电路可以接进去,想想电脑机箱后边的针孔,就是这个意思,Soga)来控制。如果有其他电路相连。这时候takeover为 0(图示状态),此时存储器由其他电路接管,控制面板上的其他开关不起作用,当takeover为1 时,控制面板将重新获得对存储器的控制能力。
最后还是给出电路实现
<img src="https://pic4.zhimg.com/50/f3282dc784fd325ac9a32d0f0dc9e642_hd.jpg" data-rawwidth="655" data-rawheight="471" class="origin_image zh-lightbox-thumb" width="655" data-original="https://pic4.zhimg.com/f3282dc784fd325ac9a32d0f0dc9e642_r.jpg">想一下,机器壳子后面的针孔连那里,控制面板的开关又连接哪里?
<img src="https://pic2.zhimg.com/50/7381d966f2b1c58ea11ed73b09e92017_hd.jpg" data-rawwidth="600" data-rawheight="372" class="origin_image zh-lightbox-thumb" width="600" data-original="https://pic2.zhimg.com/7381d966f2b1c58ea11ed73b09e92017_r.jpg">简化的图示,是不是又用到“抽象”的思想呢?
一个辛辛苦苦装满65,536字节(8位为一个字节,字节编码请去参考ASCII编码)珍贵数据的64K X 8的RAM阵列,如果断电,会发生什么事情?首先电磁铁会因为失去电流失去磁性,随着“梆”的一声,金属片讲弹回原位,RAM中的所有数据将如风中残烛一般消失在黑暗之中,所以,RAM也成为“易失性”存储器。
那我一手打造的64K X 8的存储阵列,需要多少继电器呢?答案是是500W左右,是不是惊讶到恐怖呢?谁会没事儿造出这么个恐怖的怪兽?(100年后的今天,用二极管,三极管,集成这么多元器件的芯片,连指甲盖的大小都不到,感叹人类技术的进步吧)。
我穿越回二十世纪初,再次站在专利局的门口,为我这项“伟大的发明”申请专利,瑞士专利局的爱因斯坦会因此吓尿吗?世界上最聪明的大脑,能理解“黑箱”背后发生了什么吗?
第四节 自动操作
说了这么多电子线路的知识,我相信的我的讲述方式,大家都是能看懂的,前面所写的,其实只是为大家讲述一件事儿,“把电子元器件内部实现展开”,现有的一个个电子元器件,现在就是一个个小工具(把内部实现封装起来,保留外部接口,外部接口,就是那一根根地址线,数据线,和其他开关)、原材料。那我们现在看一看现在都有那些原材料呢?
计算器:一个会算数的小朋友,每次你把要进行计算的两个数给他,拍一下小朋友的头,小朋友帮我算一下吧,他会把计算的结果给你,没有一点误差,计算速度很快,并且乐此不疲。
计数器:一个一直在数数的小朋友
存储器:辛辛苦苦装满了64K 字节的箱子
译码器:《唐伯虎点秋香》中有个代号,9527,一个数字,你说它什么意思呢?如果,我“规定”9527指的是唐伯虎,让译码器来做这件事,译码器你把9527给我带过来(地址线用2进制表示9527,9527的二进制是多少呢?),这时候译码器“很听话”的把唐伯虎叫过来。(在这里,机器“理解了”人类的语言吗?)
有了这些原材料,我们就可以着手打造一台computer了,我们的工作才刚刚开始,请读者保持耐心,我们最终要实现的是一台通用计算机,这台“先进的”机器可以使加减法的过程自动化,is that unbelievable?这台机器可以解决所有能有加、减法处理的问题,而事实上现实中的许多问题确实可以用加法与减法来解决。
让我来回顾一下自己的教育经历。从咿呀学语之后,幼儿园开始,我们就要开始一生的学习了,小学的数学课现在还叫不叫“算数”?刚开始,我们扳着自己的手指数数“1,2,3,4,5,上山打老虎...”,学会数数之后呢?老师先教我们加法与减法,那么乘法和除法呢?我依稀记得,是用加法和减法来实现的,对吗?
加法与减法,可以从底而上,构建更加复杂的算数系统,以至于,微积分也是建立的基本的算数系统之上,我还清楚的记得泰勒公式带给我的震撼,记得第一次见到牛顿迭代法时的情景。
<img src="https://pic1.zhimg.com/50/41bbe01adc4e96f1c24c8287a3c02fcb_hd.jpg" data-rawwidth="719" data-rawheight="103" class="origin_image zh-lightbox-thumb" width="719" data-original="https://pic1.zhimg.com/41bbe01adc4e96f1c24c8287a3c02fcb_r.jpg">最美的数学公式之一,不解释为什么了,参考大学微积分
假如,假如我们已经实现一台可编程的最原始的执行加减法运算的“计算机”,如何计算出e的值呢?
想明白这一切,就需要我们了解“自动操作”的过程,了解程序的本质什么?编写程序的过程就像堆多米诺骨牌,辛辛苦苦,小心翼翼堆了半天,只为了那一下推到骨牌的快感!下面这一部分内容较难,请读者一定保持耐心,我会试着按我自己的理解讲清楚,如果我有理解不对之处,欢迎大家指出来,讨论改正
新纪元-能接受“指令”的计算器
有人问我,真的可以用上述提供的那些原材料(计算器、计数器、存储器、译码器)造出一个计算机吗?就像维克多·弗兰肯斯坦组装怪物一样,当一切都已经就绪,看着我们一手打造出的庞大的怪物,小心翼翼的通上电,“醒来吧,孩子”,就像给他赋予生命一般,这些破铜烂铁奇迹般的苏醒过来,按照我给他的指令,完成我想要的工作,真的,人世间没有比这样的工作更让人神往了,你能理解《模拟游戏》中Turing对克里斯托弗的一往情深吗?至少他打动了我的心。
扯多了,我可以很明确的告诉你,只用那些原材料确实可以打造出一台计算机,并且历史上确实有人实现了!是谁?冯诺依曼?图灵?很遗憾地告诉你,no。主人公的名字,我前边已经提到了,他叫康拉德·楚泽,1935年还是一个工科学生的他,在位于柏林的家中打造出一个可编程的计算机,一共花了3000多个继电器。
接下来让我们穿越回到1935左右,让我们跟随“主人公”的思路,尝试打造出一台“计算机”。
还记得上小学时,你学完数数,学完加减法之后,大人们常常考考你的题目是什么?“你给我算一下从1一直加到100吧”,问题是,我能用机器代替我来算数吗?哦哦,简单,我的原材料里不是有“加法器”了吗?,稍作修改就行,好,看看我的设计
<img src="https://pic4.zhimg.com/50/8415ede484dafc8786a844425824df26_hd.jpg" data-rawwidth="506" data-rawheight="377" class="origin_image zh-lightbox-thumb" width="506" data-original="https://pic4.zhimg.com/8415ede484dafc8786a844425824df26_r.jpg">拿一个8位的加法器和一个8位的锁存器,按上述方式相连,每次我们可以通过加法器的开关输入我们要算的数(当然要输入的数是0-255之间,计算的结果也是0-255之间,在这里可以先计算1-10的和),我们小心翼翼的拨动开关,最后下方的一排指示灯显示计算的结果。简单吧(这个器件称作累加器)可是我一不小心输错了一个数怎么办?只有重新来算,完全再来一遍,好麻烦啊,有没有可以改进的方式呢?我突然想到,不是有存储器嘛,可不可以把我要计算的数据先存入存储器,再通过读取存储器的内容,把数据传送到加法器,执行运算,最后显示结果。
good idea!具体该怎么做呢,我给出一种实现方案
<img src="https://pic3.zhimg.com/50/c84dc8648869aa61ad0e5edd0b85ed1a_hd.jpg" data-rawwidth="633" data-rawheight="513" class="origin_image zh-lightbox-thumb" width="633" data-original="https://pic3.zhimg.com/c84dc8648869aa61ad0e5edd0b85ed1a_r.jpg">一个振荡器(想想duang,duang,duang的电铃),16位计数器(我们的存储器容量不是64K X 8么,需要16根地址线),一个64K X 8的RAM(RAM连接控制面板,控制面板可以输入数据,还记得控制面板的takeover按钮是做什么用的么?),一个8位加法器和一个8位锁存器。
让我们闭上眼睛,来想一想,这是怎么工作的。首先,请清零开关,然后闭合控制面板上的takeover按钮,这时候控制面板接管了存储器,如果要算的有100个数,我们一次调整存储器的地址线和数据线,把数据存入0000h-0063h的地址空间(这一部分你明白了吗,该怎么操作控制面板呢?上述地址空间用16进制表示)。数据输入完了,我们断开控制按钮(takeover键),这时候控制面板失去对存储器的控制,断开清零开关,这时候,计数器开始工作,0000h,电信号传入存储器的地址线,存储器呢,是一个忠实的仓库保管员,来,我看看你要取什么东西,他接过传来的地址,哦原来要0000h盒子内的东西啊,好,你拿走吧,(0000h“盒子”内的东西就是刚才输入的第一个数),第一个数据传入到加法器,加法器小朋友一看,好了,你和自身相加,这不还是你自己吗?他把计算结果给了锁存器,锁气器把计算的结果放入一个临时的盒子内。经过一点时间(很短)计数器变成0001h,还是和刚才一样,计数器小朋友把自己的数给存储器管理大叔,大叔根据传过来的数,把取出的数据传给加法器小朋友,加法器小朋友执行加法运算,把得到的结果给锁存器。他们是如此的兢兢业业,乐此不疲,“机械式”的完成自己的任务,没有一点儿怨言。
哎,计算的结果是什么?我怎么看到指示灯在闪烁,计算的结果哪里去了?哦哦哦,计数器小朋友实在是太敬业了,根本没有办法让他停止工作,当他数到FFFFh之后又从0000h开始数数了。
还有这样的计算也太机械了,功能也实在是太有限了,要是我想把100个数,分成50组,计算每一组的和,这又该怎么做到呢?聪明的读者你也动动脑袋想一想,怎么做到呢?
楚泽看到这里也许和咱们一样皱紧眉头,怎么做呢,怎么做呢?该怎样解决这个问题呢?这时候或许突然迸发出“革命性”的想法,把运算的结果存回到RAM阵列中不行吗?这样一来,就可以在适当的时候用RAM阵列 的控制面板来检查运算结果(按下takeover),为了实现这个目的,在控制面板上加一排显示灯。eureka!
改变之后的连线图
<img src="https://pic2.zhimg.com/50/8c1058d66dbed66132e9a696c7bbd67d_hd.jpg" data-rawwidth="574" data-rawheight="476" class="origin_image zh-lightbox-thumb" width="574" data-original="https://pic2.zhimg.com/8c1058d66dbed66132e9a696c7bbd67d_r.jpg">这里略去了一部分,包括振荡器和清零开关。这样做是很好,但是问题来了,怎样控制RAM写入信号呢(何时存入RAM,把结果存在什么位置?)
假如我有一个这样的计算任务要完成:首先对三个数进行求和,然后对两个数进行求和,最后再对三个数进行求和,图示如下
<img src="https://pic3.zhimg.com/50/533ffcfdeb6fc903e399114eb3882744_hd.jpg" data-rawwidth="425" data-rawheight="343" class="origin_image zh-lightbox-thumb" width="425" data-original="https://pic3.zhimg.com/533ffcfdeb6fc903e399114eb3882744_r.jpg">图中用一小段连续的纸条(标记上连续的格子)表示一小段存储器,格子内表示存的内容。怎样使自动加法器为我们完成这项任务呢?我们不能期待向RAM阵列中输入一组数,然后自动加法器自动完成任务,自动加法器怎样“理解”我们交给它的任务,它怎么“知道”我们要他们干什么?
为了完成这个任务,我们需要用一些数字代码来标示加法器需要完成的每一项工作:加载(Load)、相加(Add)、保存(Save)、终止(Halt)
有了上述的指令,我们就可以命令计算器来工作了(暂时不去了解如何实现),对于上述的任务,可以表示如下:(1)把0000h地址处的内容加载到累加器(2)把0001h地址处的内容加到累加器(3)把0002h地址处的内容加到累加器(4)把累加器中的内容存储到0003h地址处(5)把0004h地址处的内容加载到累加器(6)把0005h地址处的内容加到累加器(7)把累加器中的内容存储到0006h地址处(8)把0007h地址处的内容加载到累加器(9)把0008h地址处的内容加到累加器(10)把0009h地址处的内容加到累加器(11)把累加器中的内容存储到000Ah地址处(12)命令自动加法器停止工作
有了这些指令代码,那么这些指令代码存放在哪里呢?得了,不去想了,简单粗暴的解决方式就是在加一个RAM,一个RAM存放数据,另一个RAM存放数据对应位置的操作符(也就是上文指定的那些代码),再次对我们的机器进行改造,改造后的结果如下
<img src="https://pic4.zhimg.com/50/4c87b392ea539c41eed286cb192596b0_hd.jpg" data-rawwidth="580" data-rawheight="464" class="origin_image zh-lightbox-thumb" width="580" data-original="https://pic4.zhimg.com/4c87b392ea539c41eed286cb192596b0_r.jpg">观察要仔细啊,数据的RAM即可以通过Control Panel控制面板进行输入,也可以接受外部的数据,而存储代码RAM只能通过控制面板写入!
那么往存储代码的RAM里写入什么内容吧?机器又不认识load、store、add、halt这些单词。既然机器不认识,我就让他们认识!解决方式,就是编码,其实两位信息编码足够操作码,代码Load(加载),10hStore(保存),11hAdd(加法),20hHalt(停止),FFh
这样一来,存储代码的那个RAM里边要存的内容就一目了然了
<img src="https://pic4.zhimg.com/50/1f7b442f1eac20bb008f4f575ec32254_hd.jpg" data-rawwidth="332" data-rawheight="363" class="content_image" width="332">看到这里,读者有疑问吗?还是我最早提出的那个问题,机器是如何“理解”人类的语言的,我虽然把要操作的指令用0和1进行编码,但你把编码之后的内容拿给我们一手打造的这台机器,他还是“不明白”什么意思,去进行何种操作啊!我们转来转去又转回最初的起点,你让冷冰冰的机器去“理解”人类的指令,无异于天方夜谭,机器就是机器,永远也不可能具有思维,当初,我在这里也是困扰好久,哦,原来如此!
我已经把答案告诉你了,机器就是机器,永远也不可能具有思维
我不管你有没有思维,你必须完成我给你的任务,你把上述的任务算个结果出来,这一点儿或许能办到,嘻嘻
<img src="https://pic4.zhimg.com/50/e7c77b1509aa2d103645b5517788422e_hd.jpg" data-rawwidth="613" data-rawheight="650" class="origin_image zh-lightbox-thumb" width="613" data-original="https://pic4.zhimg.com/e7c77b1509aa2d103645b5517788422e_r.jpg">为了体现Load和Add命令,我的机器内部又进行了部分改变,你看出差别来了吗?
其实上述有一小部分没有连线。again,闭上眼睛,跟我来想想机器执行的过程,可爱的小朋友们和敬业的大叔们又来了。计数小朋友把数据给两个RAM的仓库管理员,一个取出数据,一个取出指令。数据传给累加器和2-1选择器(这是个什么鬼)?数据到了2-1选择器小朋友的面前,发现了一道门,门上写着,“此山是我栽,此树是我开,要想从此过,留下买路财”,小朋友,让我过去吧,叔叔给你糖吃,2-1选择器小朋友说,“我只有一条路,你们两个人,我让谁通过呢?”(图中,2-1选择器接收了两组数据),就在这时候,2-1选择器小朋友,收到了一条指令,这条指令来自哪里呢?哦哦,刚才管代码的RAM大叔,取出指令(10h或者,11h或者20h或者FFh),他把指令交给“指令解析器”(图中没有画)指令解析器负责把信送给2-1选择器、RAM、计数器的指令接收端(也就是2-1选择器的S,RAM的W等,在这里称为控制信号,控制信号决定机器中某些部件是否工作或者决定某些期间如何工作。例如,如果代码RAM阵列输出是load指令,2-1选择器S端收到0,如果代码RAM阵列输出是Add,2-1选择器S端收到1,操作码是指令Store时,数据RAM阵列的W收到1。实现“指令解析器”很困难吗?想一想第二节中是如何送信的,3-8译码器,译码器实现只是一种方式,当然也可以用逻辑门来实现、你明白了吗?),2-1选择器小朋友收到了0,也就是要执行Load操作,8位锁存器把临时信息保存起来。然后计数器小朋友又开始数到了0001h,这些勤劳的小朋友和勤劳的大叔又继续工作了...
用这种方式,我终于实现了我的想法,这真是一件值得高兴的事儿,我要好好休息下,等等,休息之前,顺便扩展一下我们的机器,让它也能运算减法。好简单,增加一条指令不就行了?Subtract(减)
<img src="https://pic1.zhimg.com/50/aa008dade8ed6fe728a7b082c9c3c6a3_hd.jpg" data-rawwidth="312" data-rawheight="183" class="content_image" width="312">相应的,机器内部实现再改造下,增加一个取反器
<img src="https://pic3.zhimg.com/50/baeeb55749d75c08c0c93dcf23f0d6b1_hd.jpg" data-rawwidth="670" data-rawheight="674" class="origin_image zh-lightbox-thumb" width="670" data-original="https://pic3.zhimg.com/baeeb55749d75c08c0c93dcf23f0d6b1_r.jpg">布置一道作业题,取反器的那根控制信号线接在哪里?
数据“流水”
我们从继电器打造出门电路,进而实现加法器,计数器,存储器,都是为了向我们的那个终极目标一步步前进。这就像点亮科技树的过程,一步步提高,直到实现我们的终极目标--一台可编程的通用计算机,那现在来看看,我们的科技树点亮到哪一步了,现在我们亲手打造的“能读懂人类指令的计算器”,离我们的目标还有多远?
来看看我们这台机器能不能完成我们想要完成的任务。假设现在要把56h和2A相加,然后再从中减去38h,结果是多少呢?不是有指令了吗?来,设置指令,让机器去完成
<img src="https://pic3.zhimg.com/50/232a90291d342f0f880f3e6dcbeb0533_hd.jpg" data-rawwidth="526" data-rawheight="238" class="origin_image zh-lightbox-thumb" width="526" data-original="https://pic3.zhimg.com/232a90291d342f0f880f3e6dcbeb0533_r.jpg">由于指令和数据是分开存储的,我们分别通过控制面板在RAM中输入数据,启动机器,机器就“神奇”的计算出结果,可以用个控制面板来查看计算的结果。
如果我的计算任务扩大一些,算一算1W个数的和吧?啊?10000个数,这时候我可以想象,站在台机器前面的“主人公”满脸苦逼的表情,我们小心翼翼的输入这指令,Load ...,Add ...,Add ...,Add ...,......Store ...。然后我们再输入数据,这真是个体力活儿啊!当我们终于把这一切都完成之后,启动机器,Come on,baby!计算吧
让我们再次闭上眼睛,想象机器工作的情形,计数器多么像一颗跳动的“心脏”,过一段时间发出一次“心跳”,存储器收到心跳的脉冲,从此中取出数据,数据被传送到累加器“加工厂”等待处理,要通过一道道的“门”(2-1选择器),最后会传到存储器。每每想到这里,我不禁想起在欢乐谷水上漂流的过程,穿过一道道门,经过一间间屋子,每经过一道关卡,都可能被水淋到(数据被加工),最后转了一圈回到起点,机器内部执行的过程,就是数据坐在船上“流水”的过程,不是吗?
让我们来看看机器算出来的结果,这可真是一个激动的时刻,辛辛苦苦拨了半天开关,现在要见证奇迹了。“咦”?怎么结果不对,这数值也太小了!
哦,原来如此,我的累加器只能算8位的数据,让我去安静的哭一会儿去。
你可能想到,把两个8位的加法器连在一起构成一个16位的设备,这是一种解决方案,但是,还有代价更小的解决办法。
比如要计算76ABh+232Ch,最终结果是99D7h
<img src="https://pic2.zhimg.com/50/87f0ddf5ac90750f5189a348e4d20f19_hd.jpg" data-rawwidth="123" data-rawheight="82" class="content_image" width="123">我们可以把高低位分开来算
<img src="https://pic3.zhimg.com/50/9c5acf7260d0dae4cdfba7b212890b50_hd.jpg" data-rawwidth="159" data-rawheight="114" class="content_image" width="159">低位加法
<img src="https://pic2.zhimg.com/50/94b774c728adf104ff28d0b647acee25_hd.jpg" data-rawwidth="137" data-rawheight="99" class="content_image" width="137">高位加法
最后把计算的结果写回存储器
<img src="https://pic2.zhimg.com/50/76fe75c916e3139c6ba4beda8fd6464a_hd.jpg" data-rawwidth="629" data-rawheight="301" class="origin_image zh-lightbox-thumb" width="629" data-original="https://pic2.zhimg.com/76fe75c916e3139c6ba4beda8fd6464a_r.jpg">D7h被写入地址0002h处,99h被写入地址0005h处
这是很理想的状况,因为,在上述的例子中把高低位分开计算,低位计算恰巧不存在进位的情况。如果要把76ABh和236Ch这两个16位的数相加该怎么做?ABh+6Ch=117h;1h+76h+23h=9Ah。计算的结果为9A17h,怎么解决这个问题呢?可能有读者已经想到了,加一个进位锁存器(存储进位)不就行了?那我再问一句,“那我们的指令码是不是需要扩展一下呢?怎么使得译码器来触发读取进位的信号呢?”读到这里,读者也应该和我一样,我们现在不关心具体实现细节,一定会有某种逻辑门的组合来实现,对吧?下边我给出扩展的指令码(也叫作操作码)
<img src="https://pic2.zhimg.com/50/290ff25fd013817144e290055fab5ad2_hd.jpg" data-rawwidth="502" data-rawheight="251" class="origin_image zh-lightbox-thumb" width="502" data-original="https://pic2.zhimg.com/290ff25fd013817144e290055fab5ad2_r.jpg">上述指令中,增加了一个“进位加”(Add with Carry)和“借位减”(Subtract with Borrow)有了他们,就可以极大的扩展加法器的功能,而不仅仅局限于8位数据的运算了,可以对16位,24位,32位,40位数进行加、减法操作了!比如对两个32位数7A892BCDh和65A872FFh进行加法运算。仅仅需要1条Add指令和3条Add with Carry指令
<img src="https://pic3.zhimg.com/50/fcb0b3fcf56a33e3636a7d46b9c0160a_hd.jpg" data-rawwidth="590" data-rawheight="492" class="origin_image zh-lightbox-thumb" width="590" data-original="https://pic3.zhimg.com/fcb0b3fcf56a33e3636a7d46b9c0160a_r.jpg">我们通过增加操作码指令扩展的我们的“计算器”,在通往终极目标的路上又迈出了坚实的一步,“数据流水”的方式也确实也可按照我们的意愿实现一些计算任务,但是,对于计算1W个数相加之类的任务,总不能期待一条条的输入指令吧?
让我们看看问题出在哪里。第一,对于上图来说,保存计算结果的存储单元地址不连续。第二。当前设计的自动加法器不允许在随后的计算中重复使用的前面的中间结果,一旦我们把计算的结果写回存储器,我们就无法再次读取它的值了。
产生上述情况的原因就在于,我们构造的自动加法器,代码的存储和数据的存储是同步的、顺序的,并且只能从0000h开始顺序寻址,直至停机。
要解决这个问题,需要对我们设计的加法器做一个根本性且程度极大的改变。我想几十年前第一代的计算机的设计者康拉德·楚泽,Turing等人一定会为这个问题寝食难安,因为解决了这个问题,才可以实现真正意义上的“自动操作”,这个问题也是计算器与计算机最根本的区别。
没想到会有这么多人点赞,谢谢你们的鼓励,我们的万里长征已经看到胜利的曙光了,马上就要迎来激动人心的时刻了,请保持最后的耐心。
数据“转圈圈”再次看一下我们设计的机器,代码的存储和数据的存储是同步的、顺序的,并且只能从0000h开始顺序寻址(计数器小朋友在一次计数,告诉存储器管理员大叔从哪个抽屉里取数据),直至停机。但是,如果我的数据是连续存储的,并且在任意地址保存数据(也就是说,存储器存放数据的抽屉式随意的,我们只知道抽屉的编号),该怎样去取数据进行计算,并且存储计算结果啊?这时候我突然听到一声,“你傻啊,你把要取数和存数的抽屉编号告诉我不就行了?”,管理员大叔一语惊醒梦中人,是啊,有了存储器的地址不就行了?可以把数据的地址与数据的内容分开存!这可真是石破天惊
那就再次改变我们的设计吧,
<img src="https://pic2.zhimg.com/50/890bf8d90307b3df6f8a86df61453ff3_hd.jpg" data-rawwidth="786" data-rawheight="462" class="origin_image zh-lightbox-thumb" width="786" data-original="https://pic2.zhimg.com/890bf8d90307b3df6f8a86df61453ff3_r.jpg">这次,我们把指令(代码和数据的地址称为一条指令,先得到数据的地址,在根据地址取数据)放在一个RAM中,把数据存在另一个RAM中,并加了3个8位锁存器(临时存放8位数据),示意图只画出了改变的部分,其余部分与原来保持一致(累加器和代码解析器还有相应的控制信号)。指令占1个字节,16位的数据地址占2个字节,一条指令共占用3个字节,每次从RAM中取出1个字节,所以每次取出一条完整指令需要3次计数,数据地址再次传给存储器(这里多加了一个RAM),RAM取出数据传给加法器,而代码的解析与数据传输到加法器进行计算操作也需要1次计数,这必然需要更加复杂的控制信号。
从存储器中取出一条完整指令的过程叫做取指令,机器响应指令码的一系列操作的过程叫做执行指令,虽然机器可以自动取出指令,并执行指令,你能说它是一种“有生命”的东西吗?
看到这里有人可能要问,我们现在不是假设在1935左右吗?RAM是很奢侈的(500W个继电器),能不能想法舍弃掉一个RAM?把指令(代码和数据地址)与数据存在一起就可以了,这简单,还记得2-1选择器小朋友吗?(存储器部分提到了)
<img src="https://pic3.zhimg.com/50/c8dce29efc6136ce4f8e26d279d676e3_hd.jpg" data-rawwidth="734" data-rawheight="529" class="origin_image zh-lightbox-thumb" width="734" data-original="https://pic3.zhimg.com/c8dce29efc6136ce4f8e26d279d676e3_r.jpg">很简单,得到数据地址之后,把地址回传给存储器(此时计数器小朋友的计数无效),再次根据地址取出数据。 来看一个小例子吧,计算45h+A9h-8Eh=?,假设45h,A9h,8Eh分别存在地址0010h,0011h,0012h处,计算的结果存于0013h处。我们应该给机器这样的指令:把0010h地址处的字节装入累加器,把0011h地址处的字节装入累加器,从累加器中减去0012h地址处的地址,把累加器中的内容保存到0013h地址处,停机,
数据的存储可以是任意的,我们只需要知道其相应的地址,那么指令呢?指令还是机械的顺序的往下执行,会不会出现这种情况,顺序执行指令,可是数据和指令地址冲突(要存指令的地址处已经有了重要的数据,需要跳过),指令能否跳过某一段区域,继续执行呢?
这涉及到指令寻址方式的改变(耐心听下去,我们万里长征,最终的一步来了,跨过他,前方就是一马平川),怎样跳过某一段儿区域,继续执行指令呢?那就jump啊,对,扩充一条跳转指令(Jump)
<img src="https://pic4.zhimg.com/50/3d661c746d390d611881dae08e3aef84_hd.jpg" data-rawwidth="491" data-rawheight="242" class="origin_image zh-lightbox-thumb" width="491" data-original="https://pic4.zhimg.com/3d661c746d390d611881dae08e3aef84_r.jpg">相应的机器内部实现也要改变
<img src="https://pic3.zhimg.com/50/ddaa2c668c1fc02b53a776cab39c0ffc_hd.jpg" data-rawwidth="800" data-rawheight="598" class="origin_image zh-lightbox-thumb" width="800" data-original="https://pic3.zhimg.com/ddaa2c668c1fc02b53a776cab39c0ffc_r.jpg">在上一步基础之上,增加了一条到计数器的数据通路,相当于告诉计数器小朋友,“小朋友,你下次从我告诉你的那个数开始计数,叔叔给你糖吃,乖~”
让我们回到电子线路中,计数器的实现,振荡器和D触发器串联方式(16个D触发器),我们稍作修改一下边缘型触发的D型触发器
<img src="https://pic3.zhimg.com/50/870faa339e7ae5711d40b2a32c885f27_hd.jpg" data-rawwidth="385" data-rawheight="259" class="content_image" width="385">可以不用了解上图的实现,请注意我们现在重点不在于具体实现,而在于实现某一功能,我们需要为16位计数器的每一位都设置一个这样的触发器。一旦加载了某个特定的值,计数器就开始从该值开始计数(是不是用糖果把计数器小朋友收买了,呵呵)
Jump(跳转)指令确实很有用,但是一个有条件的跳转更有用(“我是个有原则的人,除非满足我的条件才jump”),比如要计算A7h与1Ch(十进制的28)相乘的结果,和28个A7h相加的结果相同,计算过程涉及到大量的重复操作
假设乘数和被乘数以及计算结果保存在一下地址:
1000h:00h,A7h,(16位乘数保存在此处)
1002h:00h,1Ch,(16位被乘数保存在此处)
1004h:00h,00h,(16位乘积保存在这两个连续的地址空间)
<img src="https://pic4.zhimg.com/50/ea2119b4d39b1c5e3fc0ccd4fece4c16_hd.jpg" data-rawwidth="728" data-rawheight="467" class="origin_image zh-lightbox-thumb" width="728" data-original="https://pic4.zhimg.com/ea2119b4d39b1c5e3fc0ccd4fece4c16_r.jpg">当这六条指令执行完毕之后,存储器1004h和1005h地址保存的16位数与A7h乘以1的结果相同。还要把这6条指令反复执行27次才能达到乘法的目的,如果在地址0012h处置放一条Jump指令会怎样?
这个过程不会停止下来,它会一直反复执行下去!
我们需要这样一种Jump指令,它只让这个过程重复执行所需要的的次数,这种指令就是条件跳转指令,怎么实现它呢?我给出一种实现方式,简单看看就好
<img src="https://pic4.zhimg.com/50/91bc8bd72f19bb5b52109b0ecd2dea33_hd.jpg" data-rawwidth="645" data-rawheight="271" class="origin_image zh-lightbox-thumb" width="645" data-original="https://pic4.zhimg.com/91bc8bd72f19bb5b52109b0ecd2dea33_r.jpg">这种锁存器叫零锁存器,当8位加法器输出为零时他锁存的值才是1。有了进位锁存器和零锁存器以后,可以为指令表新增4条指令
<img src="https://pic3.zhimg.com/50/56f6a345657d2c745bda14515254c4c4_hd.jpg" data-rawwidth="495" data-rawheight="400" class="origin_image zh-lightbox-thumb" width="495" data-original="https://pic3.zhimg.com/56f6a345657d2c745bda14515254c4c4_r.jpg">非零跳转指令只有在零锁存器输出为0时才会跳转到指定的地址,如果上一步的加法、减法、进位加法或者借位减法运算结果为0时,将不会发生跳转。只需要在常规的跳转命令的控制信号之上再加一个控制信号
那么继续刚才提出的问题,0012h地址之后的的指令为
<img src="https://pic3.zhimg.com/50/1defccdeb670c352408f807342d75b87_hd.jpg" data-rawwidth="648" data-rawheight="473" class="origin_image zh-lightbox-thumb" width="648" data-original="https://pic3.zhimg.com/1defccdeb670c352408f807342d75b87_r.jpg">Store指令不会影响零标志位的值,只有Add、Subtract、Add with Carry、Subtract with borrow这些指令才能影响零标志位的值,当执行到地28次循环时,1004h和1005h地址保存的16位数等于A7和1Ch的乘积。1003h地址保存的值为1,他和FFh相加的结果为0.零标志位被置位!Jump If Not Zero指令不会再跳转回到0000h地址处,程序执行完成。
现在可以说,我们这台不断完善的机器真的可以称得上是一台真正意义上的computer了!条件跳转指令将计算器和计算机真正区分开来。
那么,你现在明白了吗,为什么计算机能读懂0和1?计算机和程序到底是什么?
数据被附在电流上不断地转圈圈(循环的过程),当满足某一条件之后,得到最终结果。
汇编语言
把上述机器码表示成助记符的形式
<img src="https://pic4.zhimg.com/50/f8062c691653ffebb97f03eb04beb04a_hd.jpg" data-rawwidth="679" data-rawheight="389" class="origin_image zh-lightbox-thumb" width="679" data-original="https://pic4.zhimg.com/f8062c691653ffebb97f03eb04beb04a_r.jpg">那么这个乘法的程序可以写成这种形式
<img src="https://pic1.zhimg.com/50/f4f55738206044ce2ed9c5f8ab0a6028_hd.jpg" data-rawwidth="351" data-rawheight="487" class="content_image" width="351">编码时最好不使用实际地址,用label来指代存储器中的地址空间,所以上述程序可以改写为
<img src="https://pic1.zhimg.com/50/50add86b354e02d208ca72a20387c0f0_hd.jpg" data-rawwidth="744" data-rawheight="484" class="origin_image zh-lightbox-thumb" width="744" data-original="https://pic1.zhimg.com/50add86b354e02d208ca72a20387c0f0_r.jpg">终于在春节到来之前写完了,算是圆了自己的一份小小的心愿。
写的不好,欢迎大家批评改正。
一、逻辑实现
IC数字电路中,用高电压(比如3.3V)代表1,低电压(比如0V)代表0。利用布尔代数的与、或、非基本逻辑,就可以构造出不同的电路,实现复杂的运算。
与逻辑:1与0=0、1与1=1、0与0=0
或逻辑:1或0=1、1或1=1、0或0=0
非逻辑:非1=0、非0=1
比如要实现一个1位的加法器(C=A+B):
1+0=1
1+1=0
0+0=0
因为是1位加法器,我们就不考虑进位了。那么逻辑的实现就是:
C=(A 与 非B)或(非A 与 B)
这样在逻辑上一个简单的加法器就实现了。复杂的IC数字计算电路,就是由几亿个这样的简单逻辑构成的。
在这一个层面的总结中,我们了解到,IC芯片的数学原理是布尔代数,这是芯片工作的逻辑基础。
二、电路实现
以上介绍的只是纯逻辑的实现,那么怎么在电路上把它实现出来呢?举个最简单的例子,非逻辑,我们用一个称为非门的电路来实现。
<img src="https://pic4.zhimg.com/50/190fef50ea0a1481cb5336eac2e984a6_hd.jpg" data-rawwidth="243" data-rawheight="220" class="content_image" width="243">以上是一个非门的电路表示。如果Input为高电压(代表1),Output就是低电压(代表0),反之亦然。图中,Vdd表示高电压,Vss表示低电压(接地,即为0)。
PMOS可以看做一个用G端电压控制的开关器件:如果加在G端是高电压,那么PMOS可以看做是断线,如果加在G端的是低电压,那么PMOS可以看做是一根导线。NMOS正好相反,如果G端是低电压,则是断线,如果G端是高电压,则是导线。
那么看这个非门的电路,当Input为高电压时,PMOS断线,NMOS导通,Output相当于接地(Vss),那么Output就是低电压了;当Input为低电压时,PMOS导通,NMOS断线,Output相当于接Vdd,那么就是高电压。
这样我们就在电路层面实现了最基本的门逻辑-非门。与逻辑和或逻辑可以使用相似但稍复杂的电路来实现。IC数字电路归根结底都是靠这三种电路来实现的。
在这一个层面的总结中,我们了解到,其实计算机的工作原理并没有想象中那么“智能”,其实跟用水闸开关控制水流的冲力去推动风车转动的基本思想是一致的。计算机并不“懂得”0和1,它只是靠我们精妙的组织具有特定特性的物理器件,让器件发挥自身的物理性质,从而能在电压上反应出一个计算电路的输入和输出。
有了以上总结,我们就可以研究现代IC芯片的基本器件单元:MOS管了。
三、MOS管
从以上介绍中可以看出,数字电路中最重要的器件就是MOS管了,分为PMOS和NMOS。不同于电阻、电感、电容等基础电子器件,MOS管的导通与否是通过G端的电压来控制的,那么就不能使用最基本的电阻器等原件来实现了,需要重新设计一种器件。
以NMOS为例:
<img src="https://pic3.zhimg.com/50/ffa79e850c05060b45d6f10ccdc3d4c7_hd.jpg" data-rawwidth="446" data-rawheight="299" class="origin_image zh-lightbox-thumb" width="446" data-original="https://pic3.zhimg.com/ffa79e850c05060b45d6f10ccdc3d4c7_r.jpg">以上是一个NMOS的剖面图。黄色区域为掺杂了正离子的硅,绿色区域为掺杂了负离子的硅。上面的三块灰色区域为源(Source)、栅(Gate)、漏(Drain)的电极,分别对应了非门电路中NMOS连接Vss、Input(G)、Output的三个电极。从以上非门的介绍中可以了解到,我们使用NMOS,是希望通过控制Gate的电压,来控制从Source到Drain能否导通。
如图所示,现在红色虚线勾勒出的区域,从左到右形成了一个N-P-N的结构,表示掺杂了负离子的硅-掺杂了正离子的硅-掺杂了负离子的硅。因为正负离子的同性相斥、异性相吸的特征,在P、N的交界处,会形成一段“耗尽层”,其中是没有电子的(都被同性相斥、异性相吸到其他区域去了),那么如果Gate上不加电压的话(电压为0),从Source是Drain是不能导通的,对应了以上电路分析时的断线情况。如果Gate上加上合适的电压,那么情况就不一样了,因为电压为正,那么会吸引下方红色虚线勾勒区域内的负离子到Gate的下方来(电容器原理),从而在Gate下方形成了一段有负离子(N-type)的区域,也就是说原来的掺杂了正离子的硅在Gate下方的一小段区域发生了翻转变成了掺杂了负离子的硅,这样就将Source和Drain连接了起来。因为Source和Drain本身也是连接着负离子区域,这段区域就相当于一条导线,那么从Source到Drain就导通了。这就是NMOS能通过Gate控制导通能力的原理。PMOS原理类似,只不过掺杂的离子极性和NMOS刚好是相反的。
由以上介绍我们知道,控制芯片电路中的“水闸”其实是一个运用电子的基本物理特性工作的人造器件。在现代电路中,这样的器件尺寸是非常小的,基本在100nm级别(也就是说人的头发丝的截面可以放得下几百个这样的MOS器件)。那么这么小的器件,人类是怎么制造出来的呢?
四、物理实现
了解了MOS管的功能和它的结构后,就可以继续了解CMOS工艺了。CMOS工艺的目的就是在硅晶圆上通过多道工序,建造Source、Gate、Drain结构,实现NMOS和PMOS管,从而构造出与或非门,构建出更复杂的逻辑。硅晶圆其实就是从沙子中提取出来的硅单质,我们把它制作成薄片,在表面同时制备成千上万个MOS器件,形成IC芯片。
首先介绍一下一些基本工艺的目的和原理:
1、 生长SiO2:将硅晶圆放入通了氧气的烘烤炉中,使Si氧化,在表面生成一层SiO2。一般是为了绝缘。
2、 光刻(湿法):因为半导体器件的尺寸非常小,不可能通过机械手段加工,所以只能通过刻蚀的方法。原理是先在要刻蚀的表面均匀涂抹一层光刻胶并烘干,然后通过掩膜板(上面绘制了需要刻蚀出的图像,需要刻蚀的部分为透明的,不需要刻蚀的部分用黑色阻挡),将紫外线照射到光刻胶上。光刻胶分为正胶和反胶,如果是正胶的话,照射到紫外线的部分就溶解掉了。这样,需要刻蚀的部分上覆盖的光刻胶就被紫外线透过掩膜照射溶解了,而不需要刻蚀的部分因为紫外线不能透过掩膜的黑色部分,所以仍在器件表面。这时将器件放到能溶解其表面物质的溶液中,被光刻胶覆盖的部分因为接触不到溶液,所以不会被去除,而没有光刻胶的部分就溶解掉了,于是就在器件表面形成了需要刻蚀出的图形。
3、 离子刻蚀:前序步骤和湿法光刻是一样的,都是用光刻胶形成图形。但是不同于用溶液溶解,离子刻蚀是使用高能离子打向器件表面,没有被光刻胶保护的部分就被打掉了,被光刻胶保护的部分留了下来。
然后我们就可以了解一下MOS的具体制备流程了(以下图片来自FSI)。
1、 STI浅沟槽隔离:STI的目的是为了在IC电路中,将各器件隔离开来,否则会有漏电等情况发生。STI使用SiO2作为隔离介质,因为SiO2有良好的绝缘性。
首先将切下来的硅晶圆做清洁。
<img src="https://pic2.zhimg.com/50/85c1975c81c1422c921819856dd9d7e6_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 在Si表面生长一层很薄的SiO2,然后在上面覆盖一层Si3N4。这里Si3N4起到一个占位的作用。 <img src="https://pic3.zhimg.com/50/c84e53701bfa92ad282197d259fb9f1b_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 涂抹光刻胶并烘烤,用紫外线透过掩膜进行光刻。 <img src="https://pic4.zhimg.com/50/dca7be9a8e4d502774746352a2abb79a_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 没有被掩膜黑色区域保护的光刻胶部分就被去掉了,留下了被保护的部分。 <img src="https://pic3.zhimg.com/50/3c7a508a4c9cbf8647f9ced23aa67095_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 干法刻蚀,就是离子刻蚀,没有光刻胶保护的部分被高能离子打掉了,从而形成了凹槽。 <img src="https://pic4.zhimg.com/50/41d1a4df003047553d4489c734b7e966_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 去除残留的光刻胶并清洁硅晶圆。 <img src="https://pic4.zhimg.com/50/28ae5b36dacae88b7fe5400ebff9bf72_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 在晶圆上沉积一层较厚的SiO2,因为是沉积得到的,表面很不光滑。 <img src="https://pic4.zhimg.com/50/6bda3cc20c9d965bb18b3123f15e6f6e_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 通过CMP(化学机械研磨),将不光滑的表面磨平。 <img src="https://pic1.zhimg.com/50/29671c60e27a44849347bb6ccfee2fee_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 这时用能溶解Si3N4的溶液将Si3N4去除。之前提到,Si3N4是占位的作用,它去除后,SiO2的高度就略高于晶圆表面了,这也是为了起到更好的保护隔离作用。 <img src="https://pic4.zhimg.com/50/d1bc7ddd5b79befb626c73be91bfaabf_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">2、 生长阱。阱就是之前介绍MOS管时的黄色区域,作用之前也提到过了,是为了形成N-P(阱)-N或者P-N(阱)-P这样的结构。
首先还是光刻,用掩膜留下跟需要刻蚀图形相同的部分光刻胶。
<img src="https://pic1.zhimg.com/50/218c50fbf54b0b65d011a594dc7acdb1_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 进行离子注入。假设我们是要制作NMOS,那么就注入正离子(形成P阱)。注意没有被光刻胶保护的部分会注入,而被光刻胶保护的部分就不会注入到了。 <img src="https://pic1.zhimg.com/50/8a498b5ba08a342eb7cf42d0e6f388d7_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 去除光刻胶并清洁表面。 <img src="https://pic4.zhimg.com/50/20fe65d4fe3b1c9780614a203dc4b8b9_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 退火,主要目的是为了让离子在硅晶圆中更好地扩散,形成合适尺寸的阱。 <img src="https://pic3.zhimg.com/50/14944d025f586c421b7afe2f156a565b_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">3、 制作栅(Gate)。Gate就是控制Source和Drain是否导通的部分,一般材质是多晶硅,现在有时也用其他材质了。
先对晶圆做一下清洁。
<img src="https://pic4.zhimg.com/50/a2f4ee02307fdfa67ae7bd2d0c35934f_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">在晶圆上覆盖一层多晶硅。注意,要覆盖只能是晶圆表面全部覆盖,因为尺寸太小在这一步不能可能控制它的覆盖部分,只能在后续工艺中用光刻去除不需要覆盖的部分。
<img src="https://pic1.zhimg.com/50/1c61d9ab9237263b733722ef0ae375fe_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 还是涂抹光刻胶,用紫外线透过掩膜照射,留下一部分。 <img src="https://pic1.zhimg.com/50/5a15d52d47ae03fac5f2ce7df651e3fa_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 湿法刻蚀,把没有被光刻胶保护的多晶硅去除。 <img src="https://pic1.zhimg.com/50/e9041d814ae8cd7178bd843fdd90dfa3_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 去除光刻胶并清洁。这样就留下了我们需要的多晶硅部分了。不过这一部分形成的多晶硅层还不是Gate用的多晶硅,这个叫做牺牲层,主要是为了形成真正的Gate垫背用的。原因是由于Gate的尺寸很小,目前刻蚀工艺无法形成特别精确的矩形图形,所以使用了两步工序,这一步形成的多晶硅还会在以后被刻蚀掉,具体原理不再赘述。 <img src="https://pic4.zhimg.com/50/b0065c58be57ff3dfbaddc46830b0233_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 再次覆盖一层多晶硅。 <img src="https://pic3.zhimg.com/50/5202103e351c2bd50eecf2cea8191932_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 覆盖一层电极物质,一般是金属(比如Al)。 <img src="https://pic3.zhimg.com/50/92b284be20af636884a531d7f32d7b1d_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 涂抹光刻胶并刻蚀光刻胶。 <img src="https://pic2.zhimg.com/50/de61fb56b010055fdf9a97e03ee44e2c_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 栅离子注入。没有被光刻胶保护的多晶硅部分就被注入了离子了,这是为了增强Gate的导电性。去除光刻胶并清洁。
<img src="https://pic4.zhimg.com/50/42f2184010efba4d08cc7679a656c7fb_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 继续涂抹光刻胶并刻蚀光刻胶。注意这一步形成的图形就是栅真正的结构了。 <img src="https://pic2.zhimg.com/50/38790125db96ad0fa137a8ece2c7118c_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 干法刻蚀。没有被光刻胶保护的金属(黄色部分)和多晶硅(表面红色部分)就被高能离子轰击掉了,留下了我们需要的栅结构。 <img src="https://pic2.zhimg.com/50/2da7478933d4ef26c06be1b0b0c3e904_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 去除光刻胶并清洁。 <img src="https://pic1.zhimg.com/50/cef3b3ef65348a324736d63ac0376e5e_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 在栅上覆盖一层氧化层(紫色部分),这是为了在下一步离子注入时保护栅。到这一步,栅(Gate)就制作完成了。 <img src="https://pic2.zhimg.com/50/376b57ca96660a679c26b1808a183d55_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 4、 在阱上制作Source和Drain的低掺杂部分。由MOS结构图可知,Source和Drain之间有一个N-P-N(或P-N-P结构)。之前在制作阱的时候,我们把中间的这个部分(也就是阱)制作完成了,现在就是制作两边的部分。首先还是光刻,留下部分光刻胶。
<img src="https://pic2.zhimg.com/50/28b8dc440d8082e1f6b7abcc34a4b5fb_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 离子注入,被光刻胶和栅保护的部分是注入不到离子的,而中间两块区域就被注入了和阱的极性相反的离子了,于是就形成了N-P-N或P-N-P的结构。 <img src="https://pic1.zhimg.com/50/811a9d46a0e3503585627758bf59da6b_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 去除光刻胶和保护层并清洁。 <img src="https://pic4.zhimg.com/50/a637f11170be6a60d7b1cfc04088a6ee_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 5、 形成栅两旁的保护层。这是为了防止栅和源、漏之间由于量子隧穿效应形成漏电流。用SiO2保护就可以了。沉积一层SiO2和Si3N4。
<img src="https://pic4.zhimg.com/50/4f7071855a1d7c716af204542019930e_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 直接用高能离子轰击表面,控制轰击的时间,从而就把大部分SiO2保护层去掉了,留下了栅两边的比较厚的部分。 <img src="https://pic2.zhimg.com/50/793a20d07f863ca460b4eb80d40a7c76_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 清洁表面。从以上步骤我们也可以看出, 之所以MOS工艺中要用一步步复杂的光刻、刻蚀、沉积,主要原因就是因为器件太小了,没办法直接进行机械加工操作,只能通过化学或离子轰击的方法来制作,但是这些方法又只能针对一个表面,所以需要用光刻胶和掩膜板来一次次地制作保护区域,形成我们要制备的图形。6、制作Source和Drain的高掺杂部分。之所以在制作Source和Drain时要分为高掺杂和低掺杂两块区域,是为了使用所谓LDD(轻掺杂漏极)技术,来抑制短沟道效应带来的Source和Drain之间的漏电流,并且提高MOS器件的横向耐压。
首先还是上光刻胶并刻蚀出图像。
<img src="https://pic1.zhimg.com/50/8868fbda5464cdbf8dfa79c9188633c0_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 低掺杂的离子注入,形成了两边的亮蓝色区域。 <img src="https://pic3.zhimg.com/50/5b4bdb8d37059b6385fd587d49b9d155_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 去除光刻胶并清除。 <img src="https://pic3.zhimg.com/50/3f0e3c4169522d1092bc99f2c875efbc_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 退火,使掺杂离子稍扩散。这样高掺杂和低掺杂区域共同构成了源和漏。 <img src="https://pic4.zhimg.com/50/5ae8fa52aef53e8efda7a985d4ed0b18_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 7、 金属硅化物的制备。主要是用来连接Gate和电极的,导电性介于金属和多晶硅之间。首先是清洁表面。
<img src="https://pic2.zhimg.com/50/3040de3528d5b9d102f3190f592c8d34_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 在表面覆盖一层金属硅化物。 <img src="https://pic2.zhimg.com/50/b8c9b0f86659de524ca9e492eca753c6_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 退火。 <img src="https://pic3.zhimg.com/50/db7d58ce20341c03f3eb37ccf224ae57_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 通过刻蚀等方法将不需要的金属硅化物部分去除,留下连接栅的那部分。 <img src="https://pic1.zhimg.com/50/38f694e0df4ee2ba2084c2a719e5e09b_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 再次退火。到这一步金属硅化物(栅到电极的连接部分)就制作完成了。栅的形状是L形,之后会在L的尾部连接金属电极。首先覆盖一层SiO2和Si3N4。这是MOS管和上层导线的隔离层。
<img src="https://pic1.zhimg.com/50/738efbbd47b82e6484e7e86c100fe9e7_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 涂抹光刻胶,在光刻胶上形成几个穿孔。前面两个是用来连接源和漏的,后面那个是用来连接栅的。 <img src="https://pic3.zhimg.com/50/4530f67cf59bd17c0f5f9ec8019f9494_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 干法刻蚀。用高能离子轰击晶圆表面,上一步形成的3个穿孔下方由于没有保护,SiO2隔离层就被击穿了,栅、源、漏就被暴露了出来。 <img src="https://pic4.zhimg.com/50/63f81db833037a2ef8fbd1acf1d5c06f_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 去除光刻胶并清除表面。 <img src="https://pic2.zhimg.com/50/277ae9d129293bf49860fe0466ecd405_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 在表面沉积一层金属,这样金属就填充了穿孔,从而连接了栅、源、漏,将它们引了出来。 <img src="https://pic3.zhimg.com/50/8799bf564e39488999a3d87b59c719b9_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> CMP工艺,打磨掉表面多余的金属。 <img src="https://pic4.zhimg.com/50/362afce66f17a033bfa8e07856c09a0e_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155"> 清洁表面。 <img src="https://pic1.zhimg.com/50/f93b88e104d94e1b892d107536e002c4_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">9、制作金属层。这一层就完全根据电路设计中的引线来制作了,使用的金属材质和图形都是因设计而异的。
首先沉积一层介电层(就是绝缘层,用来隔离)。
<img src="https://pic4.zhimg.com/50/321b1aae2a88cce651324e0c8dc83216_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">光刻出跟需要制备的金属层图形相同的光刻胶层。
<img src="https://pic2.zhimg.com/50/9d90a2625501fa19ed0281710f2f586d_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">干法刻蚀,用高能离子轰击,刻蚀掉不需要的介电层。
<img src="https://pic1.zhimg.com/50/dbad259b3285da8f24e9603b8b0d47d0_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">去除光刻胶并清洁。
<img src="https://pic3.zhimg.com/50/b98f88c5cd8a39dd9e376bbee67569de_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">覆盖一层金属,这层金属填充到了介电层被刻蚀出的凹槽中,连接到了下方的金属电极。
<img src="https://pic4.zhimg.com/50/19714927c9a428a13250052dd892dce9_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">CMP工序,去除掉表面多余的金属。
<img src="https://pic1.zhimg.com/50/c8f03a0faa6e3c064ab7df1924f61db3_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">清洁表面。
<img src="https://pic2.zhimg.com/50/19068d1f32c189ce784941900fc1eb2f_hd.jpg" data-rawwidth="155" data-rawheight="224" class="content_image" width="155">然后就是根据电路结构继续制作金属互联层,一层层地连接到外部电路中去。一般一个简单的芯片需要10-20层互联结构。最后就是将芯片打上与外部电路连接的电极,一块完整制作好的晶圆就产生了。一般一块晶圆上会有几十块芯片,把芯片切下来就可以测试、封装、使用了。
如此,一块芯片就制作完成了。计算机通过以高低电压形式表示的1、0状态作为输入,在芯片上的千千万万个MOS管的作用下,得到同样是以电压形式表示的输出,然后通过以电压驱动的输出设备(比如显示器)显示给用户。整个过程其实是利用了电子的物理特性和极其精妙的器件组合,获得了一个“自动化”的处理方式。
玉来了
既然是问最最原始的那个工作原理。。。从小到大,我们被告知的都是,计算机只能读懂1和0,但我好奇的是为什么计算机它就能够读懂1和0呢,它是怎么读懂的?读懂后,又是怎样进行工作的呢?嗯...我想问的就是,最最基本原始的那个工作原理
+++理论的分割线+++
最最基本原始的那个工作原理甚至都和电无关,是数学原理,布尔代数(搜索),任何可以改变状态传递信息的技术都可以拿来实现布尔逻辑,而实现了布尔逻辑,就离计算机不远了。
像是三体里面的人列计算机,就是用三体人实现计算机,这一段我直接跳了,没什么可看的,因为我懂嘛。。。
我还设想过水流+开关实现逻辑门,是可行的。
+++基础实现的分割线+++
继续正题。。。
起初, 科学家 创造计算机, 科学家 说,要先有逻辑门,然后就用真空二极管实现了逻辑门
真空管的原理去搜吧
电子计算机的原理就是利用通电、断电(或曰高电平低电平)这两个状态来表示布尔代数中的逻辑真和逻辑假从而实现布尔运算,由于这个原因,设逻辑真为1和逻辑假为0,这样就可以用计算机表示二进制的数字了。
现在的计算机用的是晶体二极管,虽然底层原理不同,但是性质是一样的,这就是编程中常说的封装和抽象的好处,你不需要关心它的原理,用它实现你的功能就行了。
所以说起来,现代电子计算机的实现,是物理原理,计算理论,是数学原理。
二极管的性质是这样的,只有一个方向可以通电,反向不通电
『想知道具体原理的可以搜索PN结』
还有三极管(还有一种性质相似的场效应管FET),性质是这样的,b通电ec通,b断电ec断
『具体原理搜索NPN结』
【【【【配图】】】】
二极管和三极管
然后可以组成逻辑电路,下面分别是与或非(AND、OR、NOT)三种逻辑门的电路实现
【【【【配图】】】】
从左到右分别是与或非三种门,x j表示输入,m表示输出
有了这三种逻辑门电路,你就可以实现任意逻辑门了,比如与非门、或非门、异或门、同或门(异或非门)。(搜索逻辑门)
(实际应用中,是以与非门(NAND(Not AND) gate)为基础原件来构建电路,因为其他所有门电路都可以用与非门构建,关于这一点,你可以思考一下)
+++逻辑的分割线+++
二进制数字的加法如下:
1+1=10
1+0=1
0+0=0
0+1=1
用上文中的逻辑门就可以实现这个加法。
不考虑进位的情况下(术语叫半加器),用一个异或门就可以实现两个数字相加,很简单,就不画图示意了,自行思考吧。。。
考虑进位的情况下(术语叫全加器),稍微有点复杂,输入通过XOR(异或门)得到结果,同时过一个电路得到进位结果
进位规则如下:
1+1进位1
1+0进位0
0+0进位0
0+1进位0
可见进位规则可以用AND(与门)得到结果,所以电路图如下:
【【【【配图】】】】
实际应用中,电路并不是凭空想的,是通过布尔逻辑运算得到一个最简逻辑表达式,然后按照这个表达式来组装电路,『请搜索数字电路』。
淘宝可以买到LED灯、二极管和三极管,虽然现在涨价了,但价格依旧感人,不到顺丰快递费就可以买一大把,有兴趣的同学可以自行购买这些元器件组装电路来玩玩。
输出端接上led灯,就可以观察到电路运行结果。
额外的,如果你把几个灯泡并联并且弄成一条线段的样子当做一个整体灯管,然后通过输入来点亮相应灯泡,就可以用来显示数字了。。
像下面这种,一共7个灯管
1点亮右边两根、2点亮相应的,以此类推
这样可以用布尔代数做出来5个输入7个输出相对应的逻辑,然后用上文的逻辑门组成电路图实现
(为啥输入是5个?)
+++分割线+++
太长了。。。
后续还有反馈电路、触发器、时序逻辑存储器等等等等,最终目标是弄出一个CPU来(如果我有时间的话)可以写一个模拟器让感兴趣的同学用逻辑门拼凑CPU(如果我还有时间的话)
『待续(应该大概真的会续)』
如果字线没有被选为高电平, 那么作为控制用的M5与M6两个晶体管处于断路,把基本单元与位线隔离。由M1 – M4组成的两个反相器继续保持其状态,只要保持与高、低电平的连接。
读取:
假定储存的内容为1, 即在Q处的电平为高. 读取周期开始时,两条位线预充值为逻辑1, 随后字线WL充高电平,使得两个访问控制晶体管M5与M6通路。第二步是保存在Q的值与位线BL的预充值相同,所以BL保持逻辑1,而Q与BL的预充值不同,使得BL经由M1与M5放电而变成逻辑0(即Q的高电平使得晶体管M1通路). 在位线BL一侧,晶体管M4与M6通路,把位线连接到VDD所代表的逻辑1 (M4作为P沟道场效应管,由于栅极加了Q的低电平而M4通路). 如果储存的内容为0, 相反的电路状态将会使BL为1而BL为0. 只需要BL与BL有一个很小的电位差,读取的放大电路将会辨识出哪条位线是1哪条是0. 敏感度越高,读取速度越快。
写入:
写入周期开始时,把要写入的状态加载到位线。如果要写入0,则设置BL为1且BL为0。随后字线WL加载为高电平,位线的状态被载入SRAM的基本单元。这是通过位线输入驱动能力设计的比基本单元相对较弱的晶体管更为强壮,使得位线状态可以覆盖基本单元交叉耦合的反相器的以前的状态。
————————————————————————————————————————————一般来说,问这个问题的和来参考的人肯定是完全没有学习相关课程的。所以我尽可能简单的从最基础的开始。请听我慢慢道来。
1.计算机怎么认识0和1的?
首先你应该听过二极管是什么,这是逻辑电路中最常见的电子器件。
额。。。又扯上“逻辑电路”了:逻辑电路是以二进制为原理、实现数字信号逻辑运算和操作的电路。
要想短短几百字说清楚还真难。不过,这里就看到“二进制”了,二进制就是问题中提到的0和1!而在实际电路中,0和1由低电平(低电压)和高电平(高电压)实现。非高即低,很容易实现。
回到逻辑电路,怎么用逻辑电路实现我们想要的一些功能呢?(这些简单功能就是计算机的基础,各项简单功能组合起来就能实现复杂的功能!)
首先,二极管具有单向导电性(原理就不说了,一下子很难懂的)。
2.计算机能用1和0做什么?
除了与门,逻辑电路中还有常见的或门,非门,或非门,与或非门等。(其中有些还要用到三极管,原理就跟上面大同小异了,只要了解的童鞋就不用管了)。
与门在电路图中的符号:
或门在电路图中的符号:
非门在电路图中的符号:
然后我们就可以用这些门电路相互组合去实现复杂的逻辑功能了。
好,有了上面这些知识,下面来个实用的: 计算机怎么做加法的?知乎有个毛病就是有许多答主喜欢长篇大论不说人话,现在我试图用最简单的话来说明这个原理:
1. 只有数字电路才基于0和1,或者说布尔逻辑进行工作。模拟电路的输入是某个范围内任意的电压,输出也是某个范围内任意的电压,输入输出是个连续函数的关系,最简单的比如说放大器的电路;如果做过相关实验的话也会熟悉用运算放大器搭建模拟计算电路的方法。模拟电路可以进行许多各种各样的计算,加减乘除甚至乘方开方,输入输出都是用连续的电压表示。
2. 模拟电路计算有个致命的缺点:输出会受到输入噪声的影响,因而变得不稳定,不适用于严格的科学计算。元件的精度、老化程度也会影响计算的精度。产生这个缺点的原因是电子元件工作在线性区域,所以输出对输入的变化很敏感。
3. 正如上面所说的,电子元件工作在线性区时,输出会对输入的变化过于敏感,不适合精确计算。那么反过来,电子元件工作在非线性区时,输出对输入的变化是不敏感的。一个典型的非线性电子元件电路有两个这样的非线性区,以共射接法的BJT晶体管为例:
输入<0.7V时,晶体管截止,输出为最高电压(假设是5V);
输入>0.75V时,晶体管进入饱和区,输出为最低电压(约为0V);
输入介于两者之间时,晶体管处于线性工作状态,函数大概是5 - (Ui - 0.7) * 100,100是放大倍数,实际上一般会比100更大。在这段区域中输出对于输入是极端敏感的,不适合数字电路工作。
而前两种状态下,输入在相当大的范围(0 - 0.7V, 0.75 - 5V)中变化时,输出都是几乎不变的,也就是说输出几乎不受噪声影响,非常适合数字电路工作。
4. 因为我们的元件普遍只有两个非线性区,所以我们不可避免地用其中一个表示0,另一个表示1,而没有其他的状态去表示2或者3或者更多了。这并不是人类特别的喜欢二进制,而是受到了元件特性的限制。因为所有的变量都只有0和1两个状态,所以所有的逻辑都可以用布尔代数表示,这就构成了数字电路的基础。二进制计算只是布尔代数逻辑的一个特例。
那么你最后就应该明白了: 计算机只能接受0和1两种输入是因为数字电路只能接受0和1两种输入,数字电路只能接受0和1两种输入是因为非线性电子元件只有两个非线性区。随手写写
#10-22更新
因为得到了赞同,想一想决定逐步把答案写得更详细一些。
因为没有参考资料,全凭记忆打字,难免有所疏漏和不准确。
#
计算机所认识的0或1是信号的高低电压。高低电压即逻辑值(0或1)来自于芯片中逻辑电路的控制,主要由CMOS器件组成。CMOS的逻辑设计详见:VLSI大规模集成电路基础等课程(偏重基于CMOS的逻辑设计)。CMOS器件的工作原理详见:半导体器件物理相关课程(偏重CMOS的器件特性和原理)。半导体器件物理的基础来自半导体物理,主要是能带理论。能带理论的基础是量子力学。(所以没有量子力学就没有现代计算机)
#10-22更新
CMOS的构造和逻辑实现原理 (懒得找图,可以搜关键字看图)
假定有一种逻辑的开关,开关的输入信号为1则开关开启,为0则开关关闭,开关连接输出信号和地(0)。则输入为1,则输出为0;输入为0,输出为高阻(z,无逻辑值)。->叫做NMOS
另一种开关相反,输入为0则开关开启,为1开关关闭,开关连接输出信号和电源(1)。则输入为0,输出为1;输入为1,输出高阻。->叫做PMOS
如果把NMOS和PMOS对称的连接到一起,结果是:输入为1,,输出为0;输入为0,输出为1,总有确定的输出值,避免了高阻的情况,即CMOS(C是对称的意思)。在逻辑上实现了反向的功能,即非门(not gate)。
如果两个NMOS串联,PMOS并联,则两个输入都为1,输出为0;一个输入为0,输出为1,形成了NAND gate,再加一个NOT gate,就是AND gate。类似的可以搭建OR gate,进而搭建所有的逻辑功能。对于任意给定的输入组合和输出组合,总可以找到一个逻辑表达实现该功能(即数字逻辑电路设计中的卡诺图)。在增加了电平和边沿触发的存储单元(D触发器等),就可以把逻辑分割成不同的部分用同步的时钟来控制->形成logic + register的时序电路。CPU等IC都是这样的电路。
CMOS是现代集成电路的主要基本结构,因为输入和输出之间没有电流,功耗较小,易于大规模集成。现代的工艺(40nm/28nm/20nm/14m)也主要是在CMOS的结构上通过工艺等多方面的改进不断缩小尺寸和降低功耗。至于如何在硅片上形成这样的MOS结构涉及到半导体工艺的知识,这又是一个非常广泛的范畴。
NMOS和PMOS的MOS指的是金属场效应管,即靠输入信号的电压(栅极),把半导体材料中的载流子(半导体中可以导电的粒子,根据N型和P型分别是电子和空穴)吸引到特定的区域,形成一个可以导电的沟道,从而实现MOS管源极和漏极之间的导通。这就是开关为什么能打开和关闭的原因。当然这是最简单的介绍,其中有很多复杂的数学模型来分析(半导体器件物理的范畴)
半导体物理和量子力学的学得太早(03-04年),10年没看,有点不记得……
下次有时间可以更新一些体系结构方面的内容
#
我的这个回答针对的是小白,不叨扰专业人士。这里没有很专业的东西,不够严谨,但有助于小白稍微理解一下计算机如何通过处理二进制信息来运转。
1. 0和1组成的是二进制的数字,计算机内部处理的是0和1其实就是说计算机内部处理的是二进制数字
2. 计算机是电设备,整个工作中处理的电信号有两个: 高电平和低电平(可以类比得理解为电容器的充电状态和放点状态),这两个信号就对应了1和0,因此,计算机内部处理的都是二进制的0和1。
3. 计算机内有可以对二进制数进行运算与传送的器件。比如二进制数的加法、一串二进制信息在内存与磁盘间的传送等,都有相应的设备,保证了计算机可以执行对二进制的各种操作。
4. 任何可存储及可处理的信息都可以用一串等价的二进制数表示。比如: 十进制的数字可以转化为二进制的数字,一句话中的每一个字或字符都可以按照某种规则用固定的二进制数来表示(可以将这样的二进制数理解为相应字或字符的代号),一段视频也可以用一串二进制数来表示(视频分为很多帧,每一帧中每个像素的值都可以对应于一个二进制数),同理,其他的各种信息(如音频等)都可以用相应的一串二进制数表示。
5. 计算机连接的一些外部设备称为外设(例如: 鼠标、键盘、显示器、打印机等)。计算机可以向外设传输二进制串,控制外设的工作,比如可以向打印机传送要打印的内容,或向打印机传送一段约定好的二进制串表示让打印机开始打印;外设也可以向计算机传输二进制串,比如敲击键盘会产生相应的高低电平,即对应的0、1串(高电平1低电平0),传入电脑后,计算机便可以判断出按下了哪个键。这样便实现了计算机对外设的控制及双方的信息传送。
综合以上几点,计算机能够通过处理高低电平的方式处理0、1二进制串,而所有的信息都可以等价地用相应的二进制串来表示,计算机内有对二进制串进行各种运算与处理的设备,计算机也可以通过传送相应的二进制串来进行外部设备的控制从而实现输入与输出,这样,在二进制的基础上,计算机工作了起来 ^_^
最简单的理解:这是一个庞大的机关兽。(参见“秦时明月”,千万不要当真!)
———原文在日报长评———
这个问题本身有个瑕疵:0和1指的是什么?
1. 我大胆的猜测题主指的是汇编代码。
高级代码(C++)经过编译后会转化为汇编代码传递给硬件,汇编是由一串特定长度的0和1组成。一般而言的64位计算机,就是指可以处理64位长度的汇编代码。而这一串0和1本身,包含了微指令以及一些变量,根据所处的位置不同,0和1们组成了不同含义的命令。
然后就是题主所问的计算机如何读懂0和1。以简单的芯片来说(如MIPS),片上系统由controller和datapath组成(不知怎么翻译)。前者可以理解成公司的管理层,后者就是具体干活的。controller接受了上文所术的微指令,就知道这个汇编代码是什么作用(比如“011001”代表读取数据)。然后controller告诉datapath哪些模块要工作,数据从哪条唯一的路走。你可以想象一下赛车,从起点到终点只能走一条路。最终,输入的数据走过规定的路径,被处理成期望的输出值。类似的过程不断上演,大量的数据经过处理后,我们就在显示器上看到反馈的结果。
2. 如果题主认为0和1指的是高低电压,那问题本身就不严谨了。
数字电路中认为有三种值:0、1和高电阻(在设计中还可认为有“不确定”状态)。而真实的电路中没有确切的高低电压值,不同系统规定了不同的电压范围代表不同的值。你甚至可以把电压分成十级,就得到了十进制。只能说现实是相对的,自然界没有明确的0|1之别,人类设计出来的规则让计算机识别了0|1。
3. 扯远一些。硅技术之后的有力候选者--量子计算机。量子本身有多个叠加态,不只两个,所以可以做到0、1、2、3……到时问题就变成了“计算机如何识别0、1、2、3?”
No,它根本不懂。就像算盘不懂你拨珠子时心中默念的口诀类似。但是这样并不妨碍最后得出你想要的结果。
至于为什么在它完全不懂的情况下,还能搞出点有用的东西,这是另一个问题。
这个问题,我必须回答一下,作为一个cs专业的学生。。。我到大二其实都不是很清楚,直到我遇到了一本神作。。。
闲话不多讲,有一本神作!绝对的神作!Charles Petzold的《Code》,这本书可以说,下至5岁孩童,上至90岁老妪,无论你是计算机小白,还是大神,都会从这本书中有所收获。真是后悔没早点看到这本书,让我一个无比讨厌自己专业的人,都开始热爱这个伟大的创造。
ps:如果你真正想了解计算机的原理的话。。。我觉得没人能比这本书讲的更通俗了
http://book.douban.com/subject/1024570/
打个广告哈:
今年港美股大牛市,如果你错过15年A股,16年楼市,17年的大牛市就不要错过了哈 盈透(美国合法券商)开户链接https://snowballsecurities.com/open?r=62195 任何问题可以咨询我
0 1对应到高低电平
基础逻辑门电路实现电路的逻辑关系
逻辑门加上向前反馈就能实现状态(时钟)
然后就能实现操作了
23333并不是计算机能读懂0和1。
计算机是人造的机器,0和1也是人类的思维逻辑中两个数字符号而已,因此,计算机“读懂”0和1,是我们人类特意把它设计成这样子的。回答得太高大上了。
先理解输入和输出怎么用0和1表示。
简单的模型:一个开关控制一个电灯的亮灭。"开关“相当于输入的0和1,灯的亮灭相当于输出的0和1. 这就是一个简单的计算机了。输入了0和1,输出了0和1.
如果使用电子技术(例如强电里面大家能看见的继电器技术),那么A模块的输出,就可以做B模块的输入。也就是说,输入给A的是”通“和”断“(开关),A输出的也可以是“通断“。
这就是单模块的工作原理。记住0和1既可以是输入,也可以是输出。0和1是你定义的。你可以把声音、键盘、鼠标等等各种输入转换成0和1.比如你按下某个键,那么相当于键盘输出了一系列的开和关的动作。计算结果的0和1表示,可以想象你的屏幕的某个点被点亮和变暗,亮是1,暗是0.
计算机的输入全部会转换成按时间轴相关的一系列开关,开和关2个状态就对应于输入的”0“和”1“。输出就对应于”灯“的开关。
计算机里面所有的”计算“、”存储“、”通信“,相当于各种元器件间的”开“”关“控制。
但必须注意,这些开关动作是按时间排序的,开关的频率达到每秒10亿次,100亿次。开关和开关之间有并行串行关系,开关和开关之间可以配合,开关的动作可以被延时,可以被记录等等。。。。。。。
这就是所谓的计算机只懂0和1. 因为所有的输入和输出,都以2个状态表示。计算机的处理就是把一系列的0和1的串,变成另外的一个或多个。一直想做个萌化版的计算机科普知识的书~
这样会不会可以吸引更多的萌妹子进入IT学科的世界啊?
——————————————————————
很简单,程序君告诉电子元件 我有00000101的代码传输给你
然后 若干元件君就说 我们一起来表示这个机器码吧
于是元件君就用自己是否通电这个萌萌的状态来表示机器码
所以来说,计算机不是能读懂1和0,而是能感受到身体里可爱的元件君 是否处在萌萌的状态。
上面的代码就转化成这个问题真的要打的这么复杂吗?
计算机读懂的不是0和1,它读懂的是通电和断电。正常情况下通电是1,断电是0。
举个例子,世界上最简单的计算机,你知道是什么吗?
是一个灯泡。
你给它通电,就相当于告诉它1,它便亮了,你给它断电,就相当于告诉它0,它便灭了。
你以为它懂0,1 ?不不,它懂得是通电还是断电。
而复杂的计算机道理是一样的,只是通电断电的情况复杂的多。
我不知道他们为什么要回答那么长“科普”
简单的说,读懂的不是“1”和“0”,而是通过低电平和高电平
这是门电路里的二极管或晶体管的导通特性决定的。
不同器件低电平电压值不同,但是只要是判定低电平我们就抽象认为为逻辑“0”,
高电平同理。
首先澄清一个概念,关于计算机的概念,什么是计算机?
人类发明的工具可以分为两类:第一类是手脚的延伸。诸如汽车、飞机等等;第二类是大脑的延伸。诸如算盘、手摇计算机、电子计算机等等。广义的计算机是指大脑的延伸。我们通常说的计算机,一般指“二进制电子计算机”,是狭义的,只是计算机里面一个小小的分支,虽然目前普及程度最高,但可以预见,将来一定会被其它形式的计算机取代,如同电子计算机取代算盘等一样。
前面为什么要强调“二进制”呢?因为,计算机不仅有二进制,还有其它进制的计算机。算盘等就不是二进制,即使是电子计算机,也有不是二进制的,运算放大器就是为模拟运算设计的。
电子时代,二进制与非二进制的竞争,以二进制完胜落幕。人们为什么选择了二进制?原因其实很简单——信息判读与表示,简单准确。夜深人静,隔壁一对情侣呢哝私语,你无法听清他们说话的内容,但却可以知道他们说没说话。辨识有没有声音和辨识声音的具体内容,前者简单太多了。同理,辨识有没有电压和辨识电压值是多少,前者简单太多了。信息判读如此,信息表示同样如此。
既然选择了二进制,电路自然是要按照二进制的特点来设计的,因此诞生了“数字电路”。我们知道,二进制只有两个符号,0和1,每一位只有两种状态,0或者1。据此而设计出来的电路也就只有两种状态,高电平或者低电平,用来表示二进制的两种状态,这就是“数字电路”。由于数字电路只能表示两种状态,0或者1,因此任何0和1以外的东东,必须转换成0与1的组合才能表示,比如2必须转换成10,3转换成11,……这样无论什么内容,在计算机里的最终表现形式都是0与1的组合。
最基本的,1是电路闭合,0是电路断开,根据逻辑不同几个输入端输出端又能组成最基本的三种门电路:与门,非门,或门,门与门叠加还能构成与非门、或非门、 与或非门……那这样只要足够多的这些基本单元,就可以运算非常复杂的东西了。
计算机基础或数字电路的一些基础课都会讲这些,我另外推荐看下《三体1》吧, 在《18. 三体、牛顿、冯.诺曼伊、秦始皇、三日连珠》有一段“人肉计算机”的剧情,很形象的解释了计算机怎么工作,引用如下:"我不知道你们的名字,"冯·诺伊曼拍拍前两个士兵的肩,"你们两个负责信号输入,就叫'入1'、'入2'吧."他又指指最后一名士兵,"你,负责信号输出.就叫'出'吧,"他伸手拨动三名士兵,"这样,站成一个三角形,出是顶端,入1和入2是底边。"
"哼,你让他们成楔形攻击队形不就行了?"秦始皇轻蔑地看着冯·诺伊曼。
牛顿不知从什么地方掏出六面小旗.三白三黑,冯·诺伊曼接过来分给三名士兵,每人一白一黑,说:"白色代表0,黑色代表1。好,现在听我说,出,你转身看着入1和入2,如果他们都举黑旗,你就举黑旗,其他的情况你都举白旗,这种情况有三种:入l白,入2黑;入l黑,入2白;入1、入2都是白。"
"我觉得你应该换种颜色,白旗代表投降。"秦始皇说。
兴奋中的冯·诺伊曼没有理睬皇帝,对三名士兵大声命令:"现在开始运行!入1入2,你们每人随意举旗,好,举!好,再举!举!"入1和入2同时举了三次旗,第一次是黑黑,第二次是白黑,第三次是黑白。出都进行了正确反应,分别举起了一次黑和两次白。
"很好,运行正确,陛下,您的士兵很聪明!"
"这事儿傻瓜都会,你能告诉联,他们在干什么吗?"秦始皇一脸困惑地问。
"这三个人组成了一个计算系统的部件,是门部件的一种,叫'与门'。"冯·诺伊曼说完停了一会儿,好让皇帝理解。
秦始皇面无表情地说:"联是够郁闷的,好,继续。"
冯·诺伊曼转向排成三角阵的三名士兵:"我们构建下一个部件。你,出,只要看到入1和入2中有一个人举黑旗,你就举黑旗,这种情况有三种组合--黑黑、白黑、黑白,剩下的一种情况--白白,你就举白旗。明白了吗?好孩子,你真聪明,门部件的正确运行你是关键,好好干,皇帝会奖赏你的!下面开始运行:举!好,再举!再举!好极了,运行正常,陛下,这个门部件叫或门。"
然后,冯·诺伊曼又用三名士兵构建了与非门、或非门、异或门、同或门和三态门,最后只用两名士兵构建了最简单的非门,出总是举与入颜色相反的旗。
冯·诺伊曼对皇帝鞠躬说:"现在,陛下,所有的门部件都已演示完毕,这很简单不是吗?任何三名士兵经过一小时的训练就可以掌握。"
"他们不需要学更多的东西了吗?"秦始皇问。
"不需要,我们组建一千万个这样的门部件,再将这些部件组合成一个系统,这个系统就能进行我们所需要的运算,解出那些预测太阳运行的微分方程。这个系统,我们把它叫做……嗯,叫做……"
"计算机。"汪淼说。
"啊--好!"冯·诺伊曼对汪淼竖起一根指头,"计算机,这个名字好,整个系统实际上就是一部庞大的机器,是有史以来最复杂的机器!"
……(后面的可以自己去看了)