2.5.5 程序设计
当计算机用户希望计算机完成某项工作,但又没有可以完成该工作的软件时,只能自行开发或委托软件开发人员去开发相应的软件。因此计算机系统需要提供相应的软件开发工具,允许用户或程序员利用这些工具开发相应的软件。软件开发工具实际上提供了扩展计算机处理能力的手段。
程序员编写程序和开发软件需要使用程序设计语言。程序设计语言是一种形式语言,为程序员提供了一套标准的基本语句和形式语法。程序员可以利用这些语句,遵循所规定的语法,编写完成具有特定功能的程序。之所以被称为“语言”,是因为程序设计语言充当了程序员和计算机之间的交流工具。程序员将自己的意图用程序设计语言写成“文章”(即程序),而计算机通过阅读、理解这样的“文章”,获知程序员的意图,并完成程序员所要求的工作。
在计算机发展的早期,程序员要使用机器语言来编写程序。机器语言指的是由CPU所提供的指令系统。程序员利用指令系统中的指令编写程序,机器语言中的指令均为0和1组成的二进制代码,CPU可以直接读入这些二进制指令并执行,因此用机器语言写的程序可以直接执行,无需任何处理。但是机器指令用二进制表示,非常难以记忆,用机器语言编写的程序也很难阅读,不利于程序员开发较为复杂的程序。
为了便于程序员记忆及阅读,人们引入了“汇编语言”的概念。汇编语言将二进制机器指令进行符号化,将其中的操作码以及地址码改用英文字符缩写(例如用ADD表示加法的操作码),远比二进制代码容易记忆。同时,用汇编语言编写的程序,可读性也比机器语言程序好得多。
同机器语言相比,汇编语言的出现为程序的编写、阅读和调试提供了便利。但是汇编语言同机器语言没有本质的不同,它只是机器语言的简单符号化。程序员利用汇编语言编写程序,仍然不是一件很轻松的事情。首先,汇编语言、机器语言和具体的CPU有关,CPU不同,指令系统就不同;也就是说,它所支持的机器语言和汇编语言也不同。这样,程序员为不同的计算机编写程序,就需要学习不同的机器语言或汇编语言;同时,即使完成同样任务的汇编语言或机器语言程序,也不能直接移植到其他的机器上执行。另外,程序员利用汇编语言和机器语言编写程序,需要了解机器的硬件细节。在汇编语言中,将数据放在何处?是在寄存器中,还是在存储器中,都需要程序员自己决定,这使得一些缺乏硬件知识的人员无法进行程序设计工作。
由于上述原因,程序员需要更加容易使用的程序设计语言。BASIC, Pascal, C等所谓高级语言就是在这样的需求下产生的。高级语言尽量使用人类语言中的词汇表示需要机器完成的动作和要处理的数据。例如,在BASIC语言中,单词print被用来表示在显示器上显示或在打印机上打印信息。正因如此,高级语言易于学习,用高级语言编写的程序也易于理解和阅读。高级语言同汇编语言有着本质的不同:汇编语言只对机器语言做了简单的符号化,语句同机器语言指令间有着简单的对应关系;而高级语言同机器语言之间缺乏这种简单对应关系,一条高级语言语句所能完成的工作可能需要十几条乃至几十条机器指令才可以完成。此外,高级语言同具体的计算机无关,利用高级语言写的程序可以很容易地在不同的计算机之间进行移植。由于高级语言把存储单元、寄存器等硬件部件隐藏起来,程序员即使没有有关的硬件知识,也可以编写出程序。为了同高级语言相区别,汇编语言和机器语言一般被认为是低级语言或面向机器的语言。
目前提出的高级语言不下百种;并且,高级语言的理念也在不断进步之中,出现了面向对象的程序设计语言。随着这些语言的出现,大型软件的开发时间也变得越来越短。以下是一段用C++语言编写的小程序,其功能是从键盘上读入a, b两个数,然后计算出3a-2b+1的值并输出。读者可凭借这个简单的程序对高级语言获得一个初步印象:
#include 〈iostream.h〉 void main() {int a, b, result; cout〈〈“Please input two numbers: \n”; cin〉〉a〉〉b; result=3*a-2*b+1; cout〈〈“result is” 〈〈result〈〈endl; }
根据前文对计算机工作原理的了解,我们知道CPU只能读取和执行二进制机器指令;换句话说,计算机所能“理解”的唯一语言是机器语言。由于汇编语言对二进制指令进行了符号化,尽管汇编语言指令与机器语言对应关系简单,但CPU并不能识别这些符号的含义,也不能执行这些符号化的指令。因此,用汇编语言编写的程序并不能直接拿到CPU上去执行,必须首先被转换成机器语言代码,才能在机器上执行。把汇编语言程序转换为机器语言代码的过程一般称为汇编,能够完成汇编任务的程序被称为汇编程序。因此,如果程序员希望利用汇编语言编写程序,首先应该在计算机上安装汇编程序,利用汇编程序将自己编写的程序汇编成机器代码后,才能在机器上执行。相对于汇编的过程,程序员用汇编语言写的程序被称做源程序,汇编后的程序通常被称做目标程序。汇编程序的任务就是把汇编语言源程序转换成机器语言目标程序。
对于利用高级语言编写的源程序也是这样。计算机不能“理解”汇编语言,当然更不能“理解”C语言等高级语言,因此用高级语言写的程序要在机器上执行,同样也要进行“翻译”处理。把高级语言源程序翻译成机器语言目标程序,有两种方式:一种称为编译;另一种称为解释。编译的过程同汇编的过程类似。当程序员写完高级语言源程序后,就交给编译程序去翻译,编译程序会首先检查源程序中是否包含错误。若有错误,就返回给程序员继续修改;若没有错误,就把源程序翻译成机器语言目标代码。在成功得到目标代码后,就可以在机器上执行目标代码程序并产生程序员所期望的运行结果。编译过程和汇编过程的区别在于其复杂性,由于高级语言语句和机器语言中的指令没有简单的对应关系,因此编译过程要比汇编过程更加复杂。
有的高级语言要求按照解释的方式执行;对于这样的高级语言,源程序写完后要交给解释程序去翻译、执行。和编译程序不同,解释程序并不试图把整个源程序翻译成目标程序后再执行目标程序。解释程序首先读入源程序的第一条语句,检查是否有错误,若没有错误,则将其转换成目标代码,并立即执行所得到的目标代码;接着再读入源程序中第二条语句,执行同样的过程;如此继续,直到处理完源程序的最后一条语句。此时对整个源程序而言,每条语句都被翻译成二进制目标代码并执行。解释程序结束后,通常也不会产生一个目标代码程序(解释过程中所产生的目标代码并不会被保存),因此若想再次执行,还必须遵循同样的过程,把源程序交给解释程序去翻译并执行。可以看出,解释程序不仅进行翻译工作,在翻译过程的同时也执行了所翻译的程序;而编译程序的工作则相对单纯,它只进行翻译工作。同时,由于解释程序最终没有产生一个目标代码程序,因此每次执行都需要源程序,而编译程序会产生一个完整的目标代码程序。编译完成后,源程序不再重要,执行时只需要目标代码程序。从执行效率而言,编译的工作方式优于解释的执行方式,因为编译后的程序执行时不再有翻译的过程。但从调试程序的角度看,解释的工作方式则比较方便。目前大多数高级语言都是编译型语言,例如Pascal, C, C++等;少数为解释性语言,如Perl语言。BASIC语言传统上属于解释型语言,不过目前基本上已经被改造为编译型语言。
随着软件技术的进步,程序设计变得越来越方便。除了这些编译程序、解释程序外,目前计算机上也提供了各种各样的集成式开发环境(integrated development enviroment, IDE)。这些集成式软件开发环境不仅仅提供编译程序的功能,也提供友好的编辑环境,协助程序员编写源程序,还提供各种程序调试手段,使得程序员很容易地发现并排除程序中的错误。例如,微软公司开发的Visual Studio系列就是这样的集成式开发环境。