计算机系统是一个众多软件运行在诸多硬件模块上的系统。
现代的大部分计算机系统都是符合冯诺依曼的“存储程序”概念和体系结构的系统。
软件系统和硬件系统都有分治法与模块化思想的体现。组成程序的函数或类(对象),组成硬件的模块,都有输入、输出及接口的实现。
世界最早的计算机ENIAC,与现代计算机有太多不同,首先是特别笨重,需要一个大房间才可以容纳下来,原因是其逻辑部件不是现在普遍使用的很小的组成大规模集成电路的晶体管,而是电子管,自然其连线也不是印刷电路,而是电缆。程序指令被存入在机器的外部电路里,其编程是通过重新连接电缆来完成的,就像搭积木一样,通过重新组合连接线路(模块),而让整个计算机来完成特定的任务,这是一种“外插型计算程序”。
自然,这样的硬连接费时费力,非常不友好。如何实现完全的“自动化”?我们可以类推要自动化生产一个产品。自然,首先要把整个生产的工艺流程(由一张张的工艺指令卡组成)描述出来,工艺指令卡的每个动作都是生产设备可以完成的动作。另外,需要的物料或部件可以通过地址自动直接拿到。还有,工艺流程卡能够按顺序直接拿取并按工艺流程卡的要求协调其它协作部分的工作。
这一整套的思想就是冯诺依曼的“存储程序”(stored program)概念,改外插型计算程序为内置,程序也被他巧妙地当作数据存进了机器内部,以便电脑一条接着一条地依次执行指令,再也不必去接通什么线路,从而使整个计算过程完全由电子计算机自动控制。符合其思想的计算机系统(冯诺依曼体系架构)必须由以下部件组成:
一组精确定义的指令集,并通过硬件(CPU)来实现这些指令。
符合某种程序语言规范要求的程序,这种程序的源代码由这种程序语言的编译器(或解释器)来翻译成二进制指令序列,这些指令序列是指令集的排序组合。不同的操作系统需要不同的编译器(或解释器),而操作系统也是与硬件(指令集)对应的。
用于存放程序和数据的存储器(可以随机访问);
能够按照程序预设的顺序读取和执行指令,产生控制信号的控制器;
这样,硬件模块的组合就由以前的硬连接实现了软连接(控制器取址、译码、产生控制信号)。
另外,如果要与用户进行交互,则还需要输入、输出设备;
人类机械物理工具介入人类智能活动的第一步,也是最基本的一步始终是有限字长二进制数字的基本计算或逻辑运算,以及对它们的存储。
真正的电子器件做计算机的开拓过程,经历了从制作部件到整机,从专用机到通用机,从“外加式程序”到“存储程序”的演变。
也就形成了协同工作的电子计算机五大部件:
1 运算器:进行逻辑运算,最基本的构成就是由开关逻辑元件(晶体管)构成的加法器;
2 控件器:从存储在内存的代码区的程序代码取码、译码,产生控制信号,协调其它部件的操作;
3 内存:任何运行的程序都必须将代码存储到内存的代码区,同时分配一个存入数据的内存空间,这个内存空间进一步细分为全局区(包括静态区)、常量只读区、栈区(存放局部变量,内存空间可重复利用)、堆区(运行时申请)。
4 输入设备:数据输入;
5 输出设备:数据输出;
用布尔代数来实现开关电路(把布尔代数的“真”与“假”和电路系统的“开”与“关”对应起来,并用1和0表示),才使得布尔代数成为数字电路的基础,所有的数学和逻辑运算,加、减、乘、除、乘方、开方等,全都能转换成二值的布尔运算。而且,逻辑电路不只是具有数据计算和处理能力,还能具有记忆能力,引入循环电路就可实现。当然实现的是电存储,断电则数据将不复存在。
硬盘是什么?硬盘上存储的文件是一种数据结构,既可以做为程序的输入(输入到内存),也可以做为程序的输出(从内存输出,存储到硬盘的文件中)。
磁存储:将磁粉附着在平滑的铝合金或玻璃圆盘基上。这些磁粉被划分成称为磁道的若干个同心圆,每个同心圆就好像有无数的小磁铁,它们分别代表着0和1状态。当小磁铁受到来自磁头的磁力影响时,其排列方向会随之改变。
固态硬盘的闪存储电路:以浮空栅极是否带电来表示存1或者0,浮空栅极带电后(譬如负电荷),就在其下面,源极和漏极之间感应出正的导电沟道,使MOS管导通,即表示存入0。若浮空栅极不带电,则不形成导电沟道,MOS管不导通,即存入1。
光存储:一次性记录的CD-R光盘主要采用(酞菁)有机染料,当此光盘在进行烧录时,激光就会对在基板上涂的有机染料,进行烧录,直接烧录成一个接一个的"坑",这样有"坑"和没有"坑"的状态就形成了‘0'和‘1'的信号,这一个接一个的"坑"是不能恢复的,也就是当烧成"坑"之后,将永久性地保持现状,这也就意味着此光盘不能重复擦写。这一连串的"0"、"1"信息,就组成了二进制代码,从而表示特定的数据。对于可重复擦写的CD-RW而言,所涂抹的就不是有机染料,而是某种碳性物质,当激光在烧录时,就不是烧成一个接一个的"坑",而是改变碳性物质的极性,通过改变碳性物质的极性,来形成特定的"0"、"1"代码序列。这种碳性物质的极性是可以重复改变的,这也就表示此光盘可以重复擦写。
我们知道,数据在计算机系统内部的流动是通过三种总线实现的,分别是数据总线、控制总线、地址总线,地址总线的宽度决定了其可以访问的内存的总的大小。就像一个国家邮政编码的长度一样,一定长度的邮政编码只能访问一定数量以内的的地区,如我们现在的邮政编码是6位数,则最多可以编码的区域就是10^6。如果地址总线的宽度是32位,则最多可以访问的地址空间就是2^32≈4G。
这样,需要解决某一个问题时,就可以用某种编程语言,考虑合适的数据结构和算法来编写一个程序,由这种语言的特定操作系统的编译器编译为exe文件,将这个文件存储到电脑的硬盘,运行后,在内存开辟存储区,控制器取指令,翻译指令,产生控制信号,协调其它部件工作,最终运行到程序的最后一条指令,完成程序的运行。
问题要数字化,既有数字编码的问题,也有数据表示的问题。数据编就是字符表示成二进制的一种编码方案(如ASCII、Unicode等)。数据表示也就是实现数据结构,数据结构既体现数据元素本身,也体现数据元素的相互逻辑关系,同时要体现数据在内存中的存储实现。数据元素的相互逻辑关系可以是一对一的线性关系,如排队的队列,也可以是一对多的树型关系,如亲属关系,也可以是多对多的图形网状关系,如一个国家以城市为节点的公路网络。而在内存中的存储关系主要有顺序存储和链式存储两种方式(通过元素的存储地址体现出来)。
至于算法,不同领域,不同的问题有不同的算法,当然也有通用的算法,如贪婪法、分治法、穷举法、回溯法等。另外,由一些编程大牛也实现了一些特定的高效的算法,如迪杰斯特拉的最短路径算法、排序的快速排序法、查找的二分查找法等。
分治法是最基本的一种编程思维,面向过程的结构化程序设计最基本的思路就是自上而下,将问题逐渐分解为一个个子问题,子问题用函数去实现。面向对象的程序设计却是自下而上,考虑问题涉及到的主体(对象),将对象涉及到的与问题相关的数据和对这些数据的操作封装到对象中,由下而上,逐渐抽象为类,并形成继承和多态关系。类与对象之间通过公共接口实现交互。在GUI程序设计中,通过消息映射、事件响应实现与用户的交互。
编程需要一种机械思维,即站在计算机的角度去思考问题,按计算机能理解的语言逐步描述,程序的描述不能有二义性。
到于计算机语言,不同的计算机语言在设计时肯定有某一领域的侧重,采用不同的编程范式,但总某些方法肯定有相同的地方,如程序控制结构,用类型系统进行数据的表示。
程序控制结构:
顺序结构:代码存放在内存的代码区就是一种用地址表示的线性结构,控制器的程序计数器就是利用这种线性结构确定每条指令(代码)的存放地址来实现读取代码的。顺序结构以外的其它结构的实质都是通过跳转实现的。
选择结构:通常用if……else……、switch……case……来实现;
循环结构:通常用for……、while……、do……while来实现;
跳转结构:如goto、continue、break、return等。
用类型系统进行数据的表示:
基本数据类型:一些数据值的类型;]
复合(结构)数据类型:数据聚集成一个集合,如数组、结构体;
类:一些对象的类型(如果是面向对象的语言);
模板:一些类或函数的类型;
以及数据的操作:各类型的运算符,函数库,以及面向对象语言的运算符重载和类库。