1.3 程序设计
由于计算思维的核心是算法,而学习算法的最佳途径就是程序设计,因此计算机程序设计课程就当仁不让地成为非计算机专业学生获得计算思维能力的最重要课程。那么,如何让学生在学习过程中最大可能地收获计算思维呢?
计算思维,笼统地讲,是像计算机科学家一样思维,即像计算机科学家一样发现问题、分析问题并最终解决问题。而完成这一系列从发现问题到解决问题的活动,最好的办法莫过于用程序表达自己的思维以获取最终结果。
程序(Program)是为实现特定目标或解决特定问题而用计算机语言编写的指令序列。平常所说的各种软件就是由程序和数据构成的。编制程序就是用计算机语言描述一个特定的任务,程序的运行就是让计算机完成该任务。例如,计算函数y = ax2 + bx + c,首先告诉计算机函数的求解方法(即在计算机上编制一段程序),再由计算机进行数据运算处理(即运行程序)。因为有通用的高级程序设计语言(如C、C++、Java等),所以计算机能正确地理解程序,人们也可以读懂计算机在显示器屏幕上输出的结果信息,这就是人与计算机之间的交流。
1.3.1 程序设计语言
什么是语言?语言就广义而言,是一套共同采用的沟通符号、表达方式与处理规则。符号会以视觉、声音或者触觉方式来传递,它的核心是符号和规则。
什么是计算机语言?计算机语言是人与计算机之间传递信息的媒介。为了使电子计算机进行各种工作,就需要有一套用以编写计算机程序的数字、字符和语法规则,由这些字符和语法规则组成的计算机各种指令(或各种语句)就构成了计算机能接受的语言。
计算机程序设计语言从最初的机器代码到今天接近自然语言的表达,经过了四代演变。一般认为机器语言是第一代,符号语言即汇编语言为第二代,面向过程的高级语言为第三代,面向对象的高级语言为第四代。
实际上人们把机器语言称为“低级语言”,把汇编语言称为“中级语言”,把面向过程或对象的语言称为“高级语言”。的确,语言的级别就是根据它们和机器的密切程度划分的:越接近机器的语言越“低级”,越远离机器的语言越“高级”。
1.机器语言
机器语言实际上就是以二进制代码形式表示的机器指令。指令必须明确CPU做什么、怎么做。CPU执行指令时需要产生完成规定操作的各种信号,使计算机中的许多部件协调完成操作。例如,在计算机的算术运算指令中,就必须指明要进行何种运算、数据的来源、运算结果的去向等。
机器指令的一般格式如下:
2.汇编语言
增加了助记符的指令集合及使用规则构成了汇编语言。例如,“ADD A,B”就是一条汇编语言指令的例子。它使用英文单词ADD代表机器语言中的“加”操作码,用字符A、B分别表示加法所需要的两个操作数。它的意思是将存储地址为A和B的内容相加,并将结果存储在A中。
3.高级语言
20世纪60年代起,出现了高级语言,这是一种与机器指令系统无关、表达形式更接近于被描述问题、更接近于自然语言和数学语言的计算机语言。高级语言分为面向过程的语言和面向对象的语言两种类型。
初学者可能会问,为什么不能直接使用机器码(机器语言代码)编制程序,这样就可以省略编译与链接过程,事情当然不会这样简单。早期确实是使用机器码编程的,它要求程序编制工程师具有非常专业的计算机硬件系统知识,熟悉指令系统的寻址方式、CPU内部工作原理、机器动作时序等复杂工作背景,这样编制的程序才能最大限度地发挥机器性能。当时的计算机主要应用在工业控制和科学计算领域,不涉及数据结构和算法研究方面的问题。
随着计算机在商业领域的大规模应用,以及在知识管理、智能研究领域的深入,计算机的主要工作逐渐变为数据的分析与处理、知识推理与求解等内容。这时,程序设计主要考虑的是数据结构设计、算法分析等内容,要求软件设计工程师从硬件系统背景中分离出来,而无须记忆大量的二进制机器码,把代码优化问题交给编译程序处理,专心研究算法与数据结构。这就需要一种面向程序设计的计算机语言,而不是面向机器的指令代码。这种计算机语言更近似于自然语言规则,容易理解,无须记忆,称为高级程序设计语言。
根据高级语言的发展过程,主要有大众化的BASIC语言,面向科学计算的FORTRAN语言,面向商业数据处理的COBOL语言、Pascal语言,以及当今最流行的结构化程序设计语言——C语言,面向对象的程序设计语言C++、Visual C++、Java等。
计算机高级语言的发展,为设计算法提供了有力工具。但是,在很多场合,如工业控制领域、操作系统对处理器实时管理等方面,需要最大限度地发挥计算机CPU的处理能力,编制高效率的程序,设计紧凑的程序代码段,具有快速的响应处理时间。这时,需要对某一类型的CPU提供专门的语言工具,它比机器码容易记忆,而编译效率优于高级语言,是面向机器硬件环境的编程语言,称为汇编语言。计算机语言的种类很多,适合各种不同的应用领域。
在基于计算思维的程序语言教学中,应该以思维为主导,应该在思考问题、分析出问题的解决方案之后才考虑程序语言的实施,语言只是服务于思维的一个工具。其语法规范、语义差异不该成为课程追求的目标,计算思维的表达能力应该放在第一位。
1.3.2 程序的编译与执行
如果想让计算机工作,就得先把程序编写出来,然后通过输入设备送到存储器中保存起来,即程序存储,接着就是执行程序的问题了。根据冯·诺依曼的设计,计算机应能自动执行程序,因为计算机语言(如C、FORTRAN等)是为了让计算机和人沟通,以人们容易理解的语法形式设计的,而计算机内部的CPU系统根据数字电路设计的不同,具有自己特殊的命令系统,在程序语言和CPU指令系统之间需要一个翻译步骤,所以,一条程序语句对应着多条CPU的指令,因此,执行程序又可以理解为CPU逐条执行指令,图1.1所示是CPU内部结构图(8086系列)。
计算机执行动作的操作指令是二进制代码,称为机器码(机器语言代码)。
已经知道了计算机用二进制编码描述外部信息的方法,那么控制计算机内部运行的指令是如何实现的呢?计算机的指令系统按功能可以分为:数据传送、算术运算、逻辑运算与移位、控制转移及处理器控制。执行一条指令又分为以下三步基本操作:
(1)取出指令:从存储器某个地址中取出要执行的指令并送到CPU内部的指令寄存器暂存。
(2)分析指令:把保存在指令寄存器中的指令送到指令译码器,译出该指令对应的微操作。
(3)执行指令:根据指令译码,向各个部件发出相应的控制信号,完成指令规定的各种操作。
图1.1 CPU内部结构图(8086系列)
因此,需要执行的程序和数据首先必须翻译成计算机的机器码形式;其次,程序代码存储在计算机存储器的某一地址区域内;最后,CPU从那个地址开始,逐条读入程序的指令,执行相应的操作。
把某种计算机语言翻译成机器码的过程称为编译,任何一种计算机语言都有特定的编译器进行这一工作,如C语言编译器。不同的厂商生产的计算机或不同类型的计算机,有不同的编译器。例如,同是C语言编译器,面向大型机的和小型机的编译器就不同,当然,也不同于个人计算机的C语言编译器,因为它们的机器码不同。另外,基于计算机的操作系统不同,编译器也不同。Windows平台下的编译器都是集成开发环境的,是便于编程人员操作的视窗形式。而UNIX环境是字符界面的,它的语言编译器相应地就是命令行启动的。
图1.2是计算机语言的源程序转换成计算机最终可执行的指令码程序的过程。其中,编译只是机器码翻译,还需要经过链接器(Link),将程序中使用的标准库函数(如输入/输出函数、数学运算函数等)插入到程序中,并且给定启动代码(应用程序和操作系统之间的接口),最终才形成计算机可执行的程序文件。
在Windows操作系统环境下,编译器和链接器被集成在一个窗口内,包括源程序编辑器(书写源程序的工具),称为集成开发环境(IDE)。
图1.2 源程序转换为可执行程序的过程