从计算简史与开关电路组合理解计算机如何识别代码
毕达哥拉斯说:万物皆数,万物皆可用整数或分数来表示。
希帕索斯(Hippasus,公元前5世纪)不以为然:一个腰为1的等腰直角三角形的斜边的长度是多少?由此引发了第一次数学危机,自此,几何学强势崛起。
中国人发现计算时需要记忆中间结果很是麻烦,发明了算盘和珠算法,计算的中间结果用不同的算珠的组合来表示。
纳皮尔发现一些大数的乘除实在是太费时间了,发明了对数,化乘除为加减。(1614年)
虽然对数表实现了计算降维,但查阅起来毕竟眼花缭乱,厚厚的书册也不便携带。不多久,一位叫甘特的英国数学家想到:既然对数表是把两个数的求积问题转换为两个对数的求和,那么,如果把一个对数视为一段可以用直尺丈量的长度,对数之和不就可以利用直尺直接量出来了吗?1620年,甘特将对数表刻到一把尺上,借助圆规一类的辅助工具,实现了这种想法。这样的工具被称为计算尺。
施卡德(Wilhelm Schickard)从时钟的齿轮技术获得灵感,建造出世界已知的第一部机械式计算器,这部机械能进行六位数的加减,并经由钟声输出答案,因此又称为「算数钟」。该机器利用11个完整的、6个不完整的链轮进行加法运算,并能借助对数表进行乘除运算。但不幸在即将完成时被毁。(1623年)
1642年,帕斯卡建造了可以实际使用的能做加减的计算器,是一种由齿轮+刻度盘组成的机器。
笛卡尔找到了坐标系这个神器,说:数形是可以合二为一的。(1637年)
莱布尼茨说,我的计算器不仅要能做加减,还要能做乘除。莱布尼茨在加减法计算器的基础上加了一个叫“步进轮”(“Stepped Reckoner”)的装置。
步进轮是一个有9个齿的长圆柱体,9个齿依次分布于圆柱表面;旁边另有个小齿轮可以沿着轴向移动,以便逐次与步进轮啮合。每当小齿轮转动一圈,步进轮可根据它与小齿轮啮合的齿数,分别转动1/10、2/10圈……,直到9/10圈,这样一来,它就能够连续重复地做加减法,在转动手柄的过程中,使这种重复加减转变为乘除运算。(1671年)
同时,莱布尼茨和牛顿两人各自独立地找到了求曲线下面积的一般方法。莱布尼茨说,求面积不过是求和,求面积的变化率不过是求差。求面积与求变化率是两个互逆的过程,这就是微积分。
巴贝奇说,为什么只把蒸汽机用于纺织业,为什么不用它来驱动计算器呢,于是发明了用蒸汽驱动的专用计算用途的差分机(由齿轮、转轮、杠杆、拉杆组合而成)。更进一步,构思了具有通用性的分析机,可以运行包含“条件”、“循环”语句的程序,有寄存器用来存储数据,但成千上万个啮合的十齿齿轮过于复杂,思想太过超前,最后以失败告终。但是,程序存储与控制的思想由此萌芽。(1837年)
布尔说,逻辑学可以和数学相结合,逻辑学的真”与“假”可以用二进制的0和1来表示。用两个字符进行组合便可以表示世间万物,只有有足够的数字位即可,这就是二进制和布尔代数。(1847年)
1854年,George Boole在《An Investigation of the laws of thought,on which are founded the mathematical theories of logic and probabilities》一文中,第一次向人们展示了如何用数学解决逻辑的问题;布尔代数简单得不能再简单了,运算的元素只有两个:1、0;或True、False,基本的运算只有“与”(“and”)、”或”(“or”)、”非”(“not”),全部的运算只用几张真值表就能表达清楚。
图灵(Alan Mathison Turing,1912-1954)头脑大风暴,用一条纸带来存储指令,用一个读写头来读写纸带上的指令并可改写纸带上的数据,这样的机器似乎可以解决自动计算的问题,这就是后人所谓的“图灵机”,存储程序概念与实现呼之欲出。
香农发现真”与“假”、0和1不就是电路系统的“开”与“关”吗,电学中的并联电路和串联电路似乎与布尔代数的逻辑与和逻辑并有点关系,既然逻辑学和数学可以相互结合,再与电学结合一下怎么样,这就是开关电路。(1938)
可以通过开关的组合来构建逻辑门(非门、与门、或门),
通过逻辑门来构建半加器、加法器:
构建记忆电路(循环电路):
计算机中的计算主要包括逻辑运算和算术运算,逻辑运算可以用计算机的门电路很自然地实现,而算术运算则皆可以以加法器为基础:
减法:减法转换为加法,减数用补码表示。
乘法:用加法和移位来计算。
除法:用加/减法和移位来计算。
以一个或多个ALU(或加法器)为核心,加上移位器和存放中间临时结果的寄存器组,在相应逻辑控制下,可实现各种运算
楚泽(Zuse)认为,计算机最重要的部分不一定是计算本身,而是过程和计算结果的传送和储存,同时发现了继电器这种更好的逻辑开关,发明了Z型系列计算机。(1940年代)
1820年,奥斯特发现电流的磁效应。1831年,美国科学家约瑟夫·亨利 (Joseph Henry 1797-1878)制造了一个电磁铁,继而利用磁铁制作了继电器。继电器是在机电式计算机第一个派上用场的电气元件。但电的作用不是作为信号而是电磁感应原理的利用。
阿坦那索夫和贝利找来了真空管作为存储与运算元件发明了ABC计算机(Atanasoff Berry Computer)。(1942)
1903年,弗莱明在真空中加热的电丝(灯丝)前加了一块板极,从而发明了第一只电子管。他把这种装有两个极的电子管称为二极管。电子管的开关特性做为计算机的逻辑部件,开关切换速度当然比继电器来得更快。此时电真正作为信号的功能而存在。
1941年6月,莫齐利拜访了阿坦那索夫并详细向其了解ABC,不久,莫齐利离开厄辛诺前往宾夕法尼亚大学的摩尔学院任教。1941年秋天,他遇到该学院电气工程系毕业的研究生艾克特。两人得到了美国军方的支持,领导开发了Eniac,号称史上第一台可变程序电子计算机。程序虽然可变,但却没有实现程序存储,只能通过开关和连接电缆(插线或插线板)来改变模块计算模块的组合,实现不同的任务。
冯·诺依曼早就认识到了Eniac不够自动,手工摁开关和连接电缆(插线)的工作似乎也可以交给计算机去做,这样的操作不都是对应于电路的通与断来实现模块的不同组合吗?不就是对应一个0和1的指令序列或者一串电信号吗?如果存储到计算机内,再按顺序读出来,然后处理为控制电信号,不就实现了不同模块的自由组合?于是1945年6月写出了长达101页的《关于离散变量自动电子计算机的草案》,提出了程序和数据一样存放在计算机内存储器中,并给出了通用电子计算机的基本架构,后来这些思想被称为存储程序控制概念和“冯·诺依曼结构”。存储程序控制也就是存储程序和程序控制,对应于硬件,也就是要实现存储器(内存)和控制器(由其进行取码、译码、发出控制信号)。存储程序控制概念是计算机理论和实践方面最重要的思想之一,可以理解为“图灵机”的具体实现,现在绝大多数计算机都是存储程序控制概念的实现或“冯·诺依曼结构”。
威尔克斯(Maurice Vincent Wilkes)使用了水银延迟线作存储器,利用穿孔纸带输入和电传打字机输出,领导、设计和制造了EDSAC(Electronic Delay Storage Automatic Calculator,电子延迟存储自动计算机),终于将存储程序控制的思想实验变成了现实。
从此,摁开关和连接电缆的工作由程序员来代替。程序员查阅计算机能够实现的指令集,将解决问题的全过程通过指令集中的指令来做排列组合,这就是程序,是一个0和1的序列,执行时加载到内存的代码区,表示指令时由控制器取指、译码、产生控制信号。指令中描述的数据存储到内存的数据区,按数据的编码规则(如补码、ASCII码等)进行解释。所以,数据和指令都由0、1的组合来表示,都存储到内存,只是做不同的解释而已。
0、1序列直接对应硬件的的两个状态,直接与电信号相对应,所以机器能直接识别,称为机器语言。
用机器语言描述程序的0、1序列,难写、难读、难改。指令集可不可以用一些单词、短语或其缩写来描述,使用名字来指代特定的内存位置,然后再用这些单词、短语或其缩写来编程,最后再翻译成机器语言?这是可行的,而查找、替换的工作也正是计算机所擅长的。用单词、短语或其缩写来描述的指令称为汇编程序,这样的翻译程序称为汇编器,将源程序翻译成机器语言的0、1序列。由此开始了程序控制程序的思想(由程序来翻译或解释另一程序)。
汇编指令与机器直接相关,一一对应,不具有通用性,且汇编指令的抽象程序过低,是否可以将一些常用功能的汇编指令组合用一些关键字、操作符来表示,地址可以用标识符来表示,以实现更高程度的抽象和封装,答案是可以的,这就是高级语言。其翻译程序称为编译器或解释器,由其来翻译由该语言规则编写的程序到机器语言。当然,对应于不同的硬件系统和操作系统(提供最基础功能,更底层的一系列程序),相同的高级语言可以实现不同的编译器或解释器。在实际当中,编译器在内部可能会被分成一个“前端”和多个“后端”。“前端”负责把高级语言的程序转换为中间形式,而“后端”则负责把中间表现形式转换成不同体系结构的汇编指令。这种做法要比使用多个完全不同的编译器更简单。
顺序、分支、循环三种控制结构便是更高程度的抽象,分支、循环的本质也是顺序结构,只不过是不同地址的跳转而已。
1958年,供职于IBM的约翰·巴库斯领导开发了世界上第一个高级语言,FORTRAN。FORTRAN说,科学计算和公式翻译交给我好了。
一些高级语言设计者觉得,区分数据类型是一个不错的选择,数据类型可以选择要求先声明,后使用,也可以选择由编译器来推断,也就是强类型与弱类型的区别,各有优劣。
另外,不同的领域可以设计出不同侧重点的高级语言,自此,各类高级语言百花齐放。
面对复杂性和需求的变动性,高级语言的设计者还面临代码如何组织的问题。
C语言说,一切都是函数。(1972年)
Smalltalk说,一切都是对象,一些数据和操作这些数据的函数因为者关系紧密,需要封装,组织成类与对象的方式。(1980年)
C++说,我是带类的C,我还可以通过模板将函数或类,让其独立于具体数据类型的。我是集成面向过程、面向对象、泛型编程思维的瑞士军刀。(1983年)
面对复杂性和需求的变动性,程序员在构建系统时还总结出来诸多的设计模式。
为了实现代码重用,常用的功能、数据结构、算法实现成了函数库、类库。所以,一个成熟的编程语言,不但具有语言的部分,编译器或解释器的部分,还要集成库、框架,以实现效率、稳定的使用需求。所以编程语言通常包含三部分,一是语言本身,二是库,三是其运行环境,也就是后面要提到的操作系统,而javascript则还有其宿主环境,也就是浏览器,浏览器也是一个应用程序,运行于特定的操作系统之上。
按照冯诺依曼结构,程序需要加载到内存(RAM)才可以被CPU随机访问。RAM是电存储,速度相对硬盘快很很多,但断电则会丢失数据,是否可以既是电存储又可以断电不丢失数据呢?答案是ROM或单片机的烧录或bios固件。程序中的0表示这条熔丝要烧断,1表示这条熔丝不烧,以此方法记录二进制信息,也是相当于逻辑电路的重新组合。程序烧录好后,芯片就有了逻辑功能。包括一次擦写的PROM和可以反复擦写的EPROM。
所以说,逻辑电路的重新组合,可以是硬连接,如Eniac的开关与连接电缆,也可以是软连接,如程序,也可以是处于中间状态的固件,如单片机的烧录或bios固件。也就是说,硬件与软件其实是硬币的两面,有时两者的界限很模糊,相应功能可以用硬件实现,也可以用软件实现。
现代系统越来越多地采用通用硬件(如处理器、内存,以及与外界相连接的接口),同时靠软件来实现特定的行为。人们普遍认为,软件更便宜、更灵活,比硬件更好修改(特别是跟已经出厂的设备比)。例如,如果用一台计算机来控制汽车的动力和刹车,那么防抱死和电子稳定控制显然应该是软件的功能。
硬件和软件一样也需要不断进行更高层次的抽象,并封装抽象。后面提到的集成电路IC、CPU都是其具体体现。
1959年,IBM制造了第一台晶体管计算机7090,使用穿孔卡片。有32K内存,系统用5K,用户用27K,用户数据在内存和一台磁鼓之间切换。计算设备的逻辑部件,从齿轮到继电器是一大进步,电的功能是产生磁,从继电器到电子管是一大进步,电开始作为电信号的功能而存在,但电子管是用玻璃管抽成真空制造而成的,所以又叫真空管,太脆弱了,想微型化很困难,功耗太大,寿命太短,不稳定。晶体管就不同了,是固体的半导体,真空管上述的一些毛病皆可克服。
1947年12月,美国贝尔实验室的肖克利、巴丁和布拉顿组成的研究小组,研制出一种点接触型的锗晶体管,晶体管特别适合用作开关,因为其固体特性。而电子管体积大、功耗大、发热厉害、寿命短、电源利用效率低、结构脆弱而且需要高压电源。
早在1952年,达默早就认识到电子线路中的分立元器件与密密麻麻的连线的不足,如何缩小元件体积,降低成本,也许封装是一种更好的选择。
1958年,供职于德州仪器公司的伊利诺斯大学毕业生杰克·基尔比渐渐形成一个天才的想法:电阻器和电容器(无源元件)可以用与晶体管(有源器件)相同的材料制造。另外,既然所有元器件都可以用同一块材料制造,那么这些部件可以先在同一块材料上就地制造,再相互连接,最终形成完整的电路。9月12日,基尔比研制出世界上第一块锗集成电路(Integrated Circuit, IC)。
1959年7月,另一位科学界和商业界的奇才罗伯特·诺伊斯(Robert Noyce)研究出一种二氧化硅的扩散技术和PN结的隔离技术,并创造性地在氧化膜上制作出铝条连线,使元件和导线合成一体。
封装成组件的集成电路相互之间以及与其它电子元件之间还是需要连接,而早在20世纪初,人们为了简化电子机器的制作,减少电子零件间的配线,降低制作成本等优点,开始钻研以印刷的方式取代配线的方法。三十年间,不断有工程师提出在绝缘的基板上加以金属导体作配线。而最成功的是1925年,美国的Charles Ducas 在绝缘的基板上印刷出线路图案,再以电镀的方式,成功建立导体作配线。直至1936年,奥地利人保罗·爱斯勒(Paul Eisler)在英国发表了箔膜技术,他在一个收音机装置内采用了印刷电路板(printed circuit boards, PCB)。
印刷电路板通过图形电镀,蚀刻出电路,还可以多层高温压制到一起:
PCB 可以大规模生产,无需焊接或用一大堆线。通过蚀刻金属线的方式,把零件连接到一起。
把 PCB 和 IC 结合使用,可以大幅减少独立组件和电线,但做到相同的功能,而且更小,更便宜,更可靠。三赢!在制成最终产品时,其上会安装集成电路、电晶体、二极管、被动元件(如:电阻、电容、连接器等)及其他各种各样的电子零件。借着导线连通,可以形成电子讯号连结及应有机能。自此,告别了传统了分立元件和传统布线。
许多早期 IC 都是把很小的封装成的独立单元,为了实现更复杂的设计,需要全新的制作工艺,于是,光刻登场!1960年,H H Loor和E Castellani发明了光刻工艺。通过多轮光刻,可以掺杂出晶体管,光刻出电阻、电容,蚀刻出细小金属导线,连接不同晶体管。光刻工艺让更微小化的集成电路成为可能。
电脑的输出可以远程做为另一台电脑的输入吗?答案就是局域网或互联网,最初建成的网络就叫做ARPANET。1969 年10 月29 日,ARPANET 上的第一条消息从加州大学洛杉矶分校发出,到达550 公里外的斯坦福大学。这一天可以看成互联网的诞生日。提供输出的称为服务器,接收输出做为输入的称为客户端。通过网线、光纤实现物理连接,通过分层的网络协议规定通信规则,由网络程序实现逻辑连接,如FTP、SMTP、Telnet、HTTP、HTML等:
1971年,全球第一个微处理器4004由Intel公司推出,采用的是MOS工艺,这是一个里程碑式的发明。
1975年,爱德·罗伯兹Ed Roberts设计了Altair 8800,采用Intel 8080处理器。事实上,微软公司的创始人比尔·盖茨和保罗·艾伦发迹,也是始于为Altair 微型计算机编写BASIC 编译器,这个编译器是微软公司的第一个产品。今天,Microsoft Visual Basic 作为BASIC 的一个主要分支,仍然被微软公司积极地维护着。
随着电脑系统的日益复杂化、以及利用电脑速度快的特点而发展出的多任务(多程序)运行方式,靠手工管理这些软、硬件资源显然不现实,唯一的办法就是用程序来管理程序,这就是操作系统,如unix、ninux、windows、ios等,操作系统本身也是许多程序的集成,相互配合完成电脑系统软、硬件的管理,实现电脑系统基础的功能支持。
20世纪50年代初,还没有应用程序与操作系统之分。计算机的能力非常有限,每次只能运行一个程序,这个程序会接管整台机器。而程序员要使用计算机,运行自己的程序,必须事先预约时间段(身份低微的学生只能预约在半夜)。随着计算机变得越来越复杂,再靠非专业人员使用它们效率就会很低。于是,操作计算机的工作就交给了专业操作员。计算机操作员的任务就是把程序输入计算机,然后把计算结果送交相应的程序员。操作系统最初就是为了代替人工操作员完成上述工作才诞生的。硬件不断发展,控制它们的操作系统也日益完善。而随着硬件越来越强大、越来越复杂,就有必要集中更多的资源来控制它们。
操作系统通常都需要管理数十个同时运行的进程或任务。其中有些是由用户启动的程序,但大多数还是一般用户看不到的系统任务。这些进程或任务(程序),要共享同一台电脑的CPU、内存、硬盘和其它输入输出设备,由操作系统统一进行控制和分配。
这些操作系统大都由C或C++来编写,是一个十分复杂的系统工程,如Windows 7 拥有大约1 亿行代码。
操作系统提供了硬件(其功能由驱动程序定义)和其他软件之间的接口。有了这个接口,硬件就好像能听懂人的话了,而程序员编程因此就会变得简单。用这个圈子里的行话说,操作系统提供了一个平台,在这平台上可以构建应用程序。
操作系统为应用程序定义了一组操作(也叫服务),提供不同编程语言的API,比如将数据存储至文件或者从文件中取出数据、建立网络连接、获取键盘输入、报告鼠标移动和按钮点击、绘制屏幕,等等。
1979年,Intel推出5MHz 8088微处理器,之后,IBM基于8088推出全球第一台PC,逐渐地,随着电脑器件的微型化,价格的逐步降低,电脑逐步普及。
最后,通用的数字系统无所不在。在整合多领域技术进步的基础上,数字设备向着小型、廉价和高性能的方向发展。某一领域的技术进步,比如存储密度,经常会影响到所有数字设备。
计算机硬件系统把大型、复杂系统切分成小型、易管理(可独立创建)的组件,软件分层、API、协议和标准莫不如此。
化学有100 多个元素,物理有十几个基本粒子。而数字计算机只有两个元素,0 和1,其他一切都由此衍生出来。比特可用来表示任何信息,从最简单的真假、是否、对错之类的二元选择,到数字、字母,乃至一切事物。复杂的事物比如购物、浏览和手机历史中关于你生活的点点滴滴,则是由简单的数据项组成,后者又可以用更简单的形式来表示,如此往复,直到表示成一个一个的比特。
计算机是操作比特的数字设备。告诉处理器做什么的指令,被编码为比特,而且通常与数据保存在同样的存储器中。改变指令可以改变计算机行为,而这也正是计算机之所以成为通用机器的原因所在。比特的含义取决于上下文,一个人的指令可能是另一个人的数据。虽然有适合处理某种数据的特定技术存在,但复制、加密、压缩、错误检测等等操作全都可以在比特的层面上执行,与比特所表示的事物无关。运行通用操作系统的通用计算机取代各种专用设备的进程还将继续。未来很可能出现根据生物计算原理设计的其他处理器,或许还会出现量子计算机。但是,数字计算机还会伴随我们很长时间。
数字网络中从一个处理器传输到另一个处理器的数据和指令,同样也都是比特。
最后,我们可以简单理解:
1 组合的概念,晶体管组合成逻辑门电路,门电路构建半加器、加法器、记忆电路。上亿个晶体管组合成一个集成电路,完成一个功能,再由数量不等的集成电路、电子元件、PCB板组合成更复杂的功能模块,通过不断抽象、分层、封装,最后组合成一台单机,通过网络组合成局域网、互联网。软件也是如此,由CPU指令抽象(组合)出高级语言的关键字、运算符、控制结构,由这些再构成语句或语句块,再组合成简单的函数或类对象完成一个小功能,不同函数或类组合到一起完成一个较大的功能,再通过接口,实现更大的功能,也是不断的抽象、分层、封装,如windows 7就有上亿行代码,包含众多相互提供接口的程序,构成一个庞大复杂的系统。
2 软硬件的逻辑等价性。
软件是可以转化为硬件的,首先是在操作系统之上的应用软件,这里主要指编译软件,它将高级语言或者汇编语言编译、解释为目标程序,也就是我们所说的机器码,然后机器码被分解为微程序,微程序再分解为微指令,而微指令就是一段定长的二进制数字,再由数字逻辑里的知识被硬件所利用。
程序还可以固化,就是将程序读入只读存储器,做成固件。对于固件,更是模糊了软件和硬件的边界。
晶体管开关的连线组合能完成一定功能(如加法机、记忆电路),就是硬件,而能完成一定功能的软件的指令序列(0、1序列)相当于晶体管开关的重新连线,因而具备了新的功能;复杂的逻辑功能单元都是由简单的逻辑电路搭建而成的,硬件就是逻辑电路的硬连接,软件就是这些逻辑电路的软连接(软件的指令序列也就是0、1序列而已)。
3 了解了Eniac的编程方式是摁开关和连接电缆(插线)来实现功能模块的组合,后续硬件的改进和存储程序控制的方式,都只是对这一手工方式的改进,所以你也可以理解,程序和其二进制的0、1序列都只是为了实现功能模块的自动组合而已,或者说是一种特殊方式的摁开关和连接电缆(插线)。所以说,相同的功能模块,可以用硬件实现,也可能由硬件+软件来实现,只是组合或连接的方式不同而已(硬连接、软连接)。
4 不管是纸带、磁带、键盘、硬盘输入,都是通过一定的技术手段转换为电信号,对应逻辑开关的通、断或高、低电平。加载到内存后,就可以被CPU的控制器取码、译码来产生控制信号,读取数据,执行算术或逻辑运算,输出数据。