Chia°dow 第24章高级语言和低级语言 用机器码编程就像用牙签吃东西,刺的块很小且做起来很费力,吃一顿饭要花很长时间。 同样,每个机器码字节只是完成可以想像得到的最小且最简单的计算工作一一从内存装入 个数至处理器,与把它另一个数相加,再把结果存回到内存—一所以,很难想像机器码如何 完成一整项的工作。 至此,我们至少已从第22章开始处的原始模型阶段有了一些进步,从前我们一直用控制 面板上的开关输入二进制数据到内存。在第22章里,介绍了如何写简单的程序用键盘输入并 在视频显示器上检查机器码的十六进制字节码。这当然不错,但还不是改进的终点。 正如我们所知道的,机器码字节与某些短的助记符相关联,如MOV、ADD、CALL和 HLT,因此,可以用一些模糊类似的英语来引用机器码。这些助记符通常与操作数写在一起, 进一步表明机器码指令的功能。例如:8080机器码字节46h使得微处理器把寄存器对HL中的 16位数寻址的内存单元所存放的内容传送到寄存器B。这可以很简明地写成 当然,用汇编语言编写程序比用机器码要容易得多,但微处理器并不能理解汇编语言。 我们已经讲过如何在纸上编写汇编程序,只有当想在微处理器上运行汇编语言程序的时候, 才会手工汇编程序,意思是把汇编语言语句转换成机器码字节并输入到内存。 如果能让计算机来做这项转换工作就更好了。如果你正在8080计算机上运行CPM操作系 统,则你已经具有了所需要的工具。下面介绍它是如何工作的 首先,建立一个文本文件,包含有你用汇编语言编写的程序。可以用CP/M程序 ED COM 来完成这项工作。该程序是一个文本编辑器,可用来创建、修改文本文件。现假设创建的文 本文件名称为 PROGRAMI.ASM。ASM文件类型表明该文件是汇编语言程序文件,该文件看 起来就像下面这样: ORG 100 MVI C,9 CALL 5 Text: DB Hello! s END 文件中有几个语句以前没有见过。第一个是ORG( origin)语句,该语句不对应于任何一条 080指令,它表示下一条语句的地址从地址0100h处开始。前面讲过,这就是CP/M程序装入 到内存的地址。 下一个语句是LXI( load extended immediate)指令,它装入一个16位数到寄存器对DE 本例中,16位数由标号Text给出。标号在程序的下部,DB( Data Byte)语句之前。DB也是 以前未见到的,DB语句后面可以是几个逗号隔开的字节或(就像本例中)在单引号里的一些 符
下载 第24章 高级语言和低级语言 用机器码编程就像用牙签吃东西,刺的块很小且做起来很费力,吃一顿饭要花很长时间。 同样,每个机器码字节只是完成可以想像得到的最小且最简单的计算工作—从内存装入一 个数至处理器,与把它另一个数相加,再把结果存回到内存—所以,很难想像机器码如何 完成一整项的工作。 至此,我们至少已从第 2 2章开始处的原始模型阶段有了一些进步,从前我们一直用控制 面板上的开关输入二进制数据到内存。在第 2 2章里,介绍了如何写简单的程序用键盘输入并 在视频显示器上检查机器码的十六进制字节码。这当然不错,但还不是改进的终点。 正如我们所知道的,机器码字节与某些短的助记符相关联,如 M O V、A D D、C A L L和 H LT,因此,可以用一些模糊类似的英语来引用机器码。这些助记符通常与操作数写在一起, 进一步表明机器码指令的功能。例如: 8 0 8 0机器码字节4 6 h使得微处理器把寄存器对 H L中的 1 6位数寻址的内存单元所存放的内容传送到寄存器 B。这可以很简明地写成: MOV B,[HL] 当然,用汇编语言编写程序比用机器码要容易得多,但微处理器并不能理解汇编语言。 我们已经讲过如何在纸上编写汇编程序,只有当想在微处理器上运行汇编语言程序的时候, 才会手工汇编程序,意思是把汇编语言语句转换成机器码字节并输入到内存。 如果能让计算机来做这项转换工作就更好了。如果你正在 8 0 8 0计算机上运行C P / M操作系 统,则你已经具有了所需要的工具。下面介绍它是如何工作的。 首先,建立一个文本文件,包含有你用汇编语言编写的程序。可以用 C P / M程序E D . C O M 来完成这项工作。该程序是一个文本编辑器,可用来创建、修改文本文件。现假设创建的文 本文件名称为P R O G R A M 1 . A S M。A S M文件类型表明该文件是汇编语言程序文件,该文件看 起来就像下面这样: ORG 0100h LXI DE, Text MVI C,9 CALL 5 RET Text: DB 'Hello!$' END 文件中有几个语句以前没有见过。第一个是 O R G(o r i g i n)语句,该语句不对应于任何一条 8 0 8 0指令,它表示下一条语句的地址从地址 0 1 0 0 h处开始。前面讲过,这就是 C P / M程序装入 到内存的地址。 下一个语句是L X I(load extended immediate)指令,它装入一个 1 6位数到寄存器对D E。 本例中,1 6位数由标号Te x t给出。标号在程序的下部, D B(Data Byte)语句之前。 D B也是 以前未见到的,D B语句后面可以是几个逗号隔开的字节或(就像本例中)在单引号里的一些 字符
inapub.com 4章高要语言和语言253 下载 MvI( move immediate)语句把数9送到寄存器C。CALL5语句进行CP/M功能调用。功 能9的意思是:显示一个字符串,起始地址由寄存器对DE给出,遇到美元符号结束。(注意, 文本以美元符号作为字符串的结束是很奇怪的,但CP/M就采用这种方法。)最后的RET语句 用来结束程序并把控制权返还给CPM(这实际上是结束CPM程序的几种方法之一)。END语 句表示汇编语言文件结束 即然已经有了7行文本的文本文件,下一步是汇编该文件,即把它转换成机器码。以前是 用手工来完成,自从运行CPM后,可以用包含在CP/M中的名为 ASM. COM的程序来完成。这 个程序是CPM汇编程序,在CP/M命令行运行 ASM. COM,方法为 ASM程序汇编 PROGRAMLASM文件并创建新的文件,名为 PROGRAM1COM,它含有 与编写的汇编语言程序相对应的机器码(实际上,在这个过程中还有另外一步,但在这里并 不重要)。现在,在CP/M命令行就可以运行 PROGRAM1COM,结果显示字符“Hell”,然 后结束。 PROGRAM1COM文件包含有下面16个字节 前面3个字节是LXI指令,紧接着2个字节是MVI指令,再后面3个字节是CALL指令,然后是 RET指令,最后7个字节是“ Hello”、感叹号和美元符号的ASCⅡ码 像 ASM COM这样的汇编程序所做的工作是:读入一个汇编语言程序(常称作源代码文件) 产生一个包含有机器码的文件——可执行文件。从大的方面来看,汇编程序是相当简单的程 序,因为在汇编语言助记符与机器码之间存在一一对应的关系。汇编程序把每一个文本行分 成助记符和参数,然后把这些单词和字符与一张表相对照,该表中存有所有可能的助记符和 参数。通过这种对照就可以找到每个语句所对应的机器码指令。 注意汇编程序是如何得出LXI指令必须把寄存器对DE设置为地址010%h的。如果LⅪI指令 本身在0100h处(CP/M把程序装入内存运行时的地址),则0109h是就Text字符串的开始地址。 通常,使用汇编程序的程序员并不需要关心程序各部分的地址 当然,第一个编写汇编程序的人必须手工汇编程序。在同一台计算机上编写新的(或改 进)汇编程序的人可以用汇编语言编程然后用最初的汇编程序来汇编。一旦新的汇编程序经 过了汇编,它也可用来汇编自身 当一个新的微处理器诞生,就需要新的汇编程序。新的汇编程序可以在已有的计算机 上编写,利用原有的汇编程序来汇编。这种汇编称之为交叉汇编,即用在计算机A上的汇编程 序来生成在计算机B上运行的代码。 尽管汇编程序消除了汇编语言编程缺少创造性这一问题(手工汇编部分),但汇编语言还 存在两个主要问题,第一个(也许你已经猜测到了)是汇编语言程序冗长、乏味。因为你是 在微处理器芯片级编程,所以必须要考虑每一个细节。 第二个问题是汇编语言不可移植。如果为 Intel8080编写汇编语言程序,则不适用于在 Motorola的6800上运行,必须用6800的汇编语言重新编程。也许,这不像编写最初的汇编语 言程序那么困难,因为已经解决了主要的组织和算法问题,但是,仍然有许多工作要做。 上一章解释了现代微处理器芯片如何集成机器码指令来进行浮点运算,这当然已经很方 便了,但还不是十分令人满意。一种选择是彻底放弃与处理器相关的实现每个基本算术操作
M V I(move immediate)语句把数9送到寄存器C。CALL 5 语句进行C P / M功能调用。功 能9的意思是:显示一个字符串,起始地址由寄存器对 D E给出,遇到美元符号结束。(注意, 文本以美元符号作为字符串的结束是很奇怪的,但 C P / M就采用这种方法。)最后的R E T语句 用来结束程序并把控制权返还给 C P / M(这实际上是结束C P / M程序的几种方法之一)。E N D语 句表示汇编语言文件结束。 即然已经有了7行文本的文本文件,下一步是汇编该文件,即把它转换成机器码。以前是 用手工来完成,自从运行 C P / M后,可以用包含在C P / M中的名为A S M . C O M的程序来完成。这 个程序是C P / M汇编程序,在C P / M命令行运行A S M . C O M,方法为: ASM PROGRAM1.ASM A S M程序汇编P R O G R A M 1 . A S M文件并创建新的文件,名为 P R O G R A M 1 . C O M,它含有 与编写的汇编语言程序相对应的机器码(实际上,在这个过程中还有另外一步,但在这里并 不重要)。现在,在C P / M命令行就可以运行 P R O G R A M 1 . C O M,结果显示字符“ H e l l o !”,然 后结束。 P R O G R A M 1 . C O M文件包含有下面1 6个字节: 11 09 01 0E 09 CD 05 00 C9 48 65 6C 6C 6F 21 24 前面3个字节是L X I指令,紧接着 2个字节是M V I指令,再后面 3个字节是C A L L指令,然后是 R E T指令,最后7个字节是“H e l l o”、感叹号和美元符号的A S C I I码。 像A S M . C O M这样的汇编程序所做的工作是:读入一个汇编语言程序(常称作源代码文件), 产生一个包含有机器码的文件—可执行文件。从大的方面来看,汇编程序是相当简单的程 序,因为在汇编语言助记符与机器码之间存在一一对应的关系。汇编程序把每一个文本行分 成助记符和参数,然后把这些单词和字符与一张表相对照,该表中存有所有可能的助记符和 参数。通过这种对照就可以找到每个语句所对应的机器码指令。 注意汇编程序是如何得出 L X I指令必须把寄存器对 D E设置为地址0 1 0 9 h的。如果L X I指令 本身在0 1 0 0 h处(C P / M把程序装入内存运行时的地址),则0 1 0 9 h是就Te x t字符串的开始地址。 通常,使用汇编程序的程序员并不需要关心程序各部分的地址。 当然,第一个编写汇编程序的人必须手工汇编程序。在同一台计算机上编写新的(或改 进)汇编程序的人可以用汇编语言编程然后用最初的汇编程序来汇编。一旦新的汇编程序经 过了汇编,它也可用来汇编自身。 每当一个新的微处理器诞生,就需要新的汇编程序。新的汇编程序可以在已有的计算机 上编写,利用原有的汇编程序来汇编。这种汇编称之为交叉汇编,即用在计算机A上的汇编程 序来生成在计算机B上运行的代码。 尽管汇编程序消除了汇编语言编程缺少创造性这一问题(手工汇编部分),但汇编语言还 存在两个主要问题,第一个(也许你已经猜测到了)是汇编语言程序冗长、乏味。因为你是 在微处理器芯片级编程,所以必须要考虑每一个细节。 第二个问题是汇编语言不可移植。如果为 Initel 8080编写汇编语言程序,则不适用于在 M o t o r o l a的6 8 0 0上运行,必须用 6 8 0 0的汇编语言重新编程。也许,这不像编写最初的汇编语 言程序那么困难,因为已经解决了主要的组织和算法问题,但是,仍然有许多工作要做。 上一章解释了现代微处理器芯片如何集成机器码指令来进行浮点运算,这当然已经很方 便了,但还不是十分令人满意。一种选择是彻底放弃与处理器相关的实现每个基本算术操作 第24章 高级语言和低级语言 253 下载
254编的奥 Chad∴cow 的机器码,取而代之的是用代数符号来表示许多数学运算。以下是一个例子: A×sin(2×pI+B)/C 这里A、B和C是数字,PI=3.14159。 既然如此,何乐而不为呢?如果这样的一条语句是在一个文本文件里,则可以编写汇编 语言程序读取文本文件并把代数表达式转换成机器代码 如果只计算一次这样的代数表达式,则可以手算或用计算器计算。如果需要用不同的 C值来计算表达式的值,则可能需要考虑如何用计算机来计算。正因为如此,代数表达式 不可能单独出现,应该考虑到表达式的上下文,用不同的值代入计算。 现在已开始创建所谓的高级程序设计语言。汇编语言称作低级语言,因为它与计算机硬 件密切相关。尽管“高级”用来描述除汇编语言以外的任何程序设计语言,但这些语言中, 些语言还比另一些语言更要高级一些。如果你是一家公司的总裁,且坐在计算机前输入 “计算全年的收益和支出,做出年度报表,打印两千份给所有的股东”,那么你确实正在用非 常高级的语言工作。在现实生活中,程序设计语言并没有达到这样理想的境界。 人类语言是千百年来复杂的影响、随机变化和不断适应的结果,即使像世界语这样的人 工语言也来源于现实语言。然而,高级计算机语言是审慎而周密的概念语言。发明程序设计 语言面临的挑战是如何使语言具有吸引力,因为语言定义了人们如何向计算机发送指令。从 20世纪50年代开始到1993年,估计已发明和实现了1000多种高级语言。 当然,这还并不足以简单地定义高级语言(它牵涉到语言所采用的语法),还必须有编译 程序用来将高级语言语句转换成机器码。像汇编程序一样,编译程序需要一个字符接一个字 符地读取源代码文件,并分解成短语、符号和数字,但编译程序比汇编程序更复杂。从某种 意义上讲,汇编程序较简单,因为在汇编语言语句与机器码之间有一一对应的关系。编译程 序通常需要把一条高级语言语句转换成许多机器码指令。编译程序不容易编写,许多书中描 述了它们的设计与构造,所以本书不作介绍了。 高级语言有优点也有缺点。最主要的优点是高级语言比汇编语言容易学且容易编写。用 高级语言编写的程序清晰、简明。高级语言通常是可移植的——也就是说,它不像汇编语言 那样依赖于特定的处理器。所以,程序设计员不需要知道程序将要运行其上的机器的内部结 构。当然,如果需要让程序在不止一种处理器上运行,则需要相应的编译程序生成针对这些 处理器的机器码。可执行文件仍然只适用于某一个处理器。 另一方面,差不多都是如此,一个好的汇编语言程序设计员可以写出比编译程序所能产 生的更优化的代码。也就是说,用高级语言编写的程序所产生的可执行文件比用汇编语言编 写功能相同的程序所产生的可执行文件要大,且执行速度较慢。(最近几年,随着微处理器的 日趋复杂以及编译程序在优化代码方面的日趋成熟,这种差别已变得不很明显。) 还有,尽管高级语言使得处理器更容易使用,但并没有使它的功能更强大。而使用汇编 语言可以最大限度地利用处理器的能力。因为高级语言需要转换成机器码,所以高级语言只 会降低处理器的能力。如果一个高级语言是真正可移植的,则它不能使用某种处理器的独有 特点。 例如,许多处理器都有移位指令。前面讲过,这些指令把累加器中的位向左或向右移动。 但是,几乎没有高级语言有这样的操作。如果程序中要用到移位,则需要用乘2或除2操作来 处理(其实,现在许多编译程序都用处理器的移位指令来实现乘或除以2的幂)。许多高级语
的机器码,取而代之的是用代数符号来表示许多数学运算。以下是一个例子: A×Sin(2×PI+B)/C 这里A、B和C是数字,PI = 3 . 1 4 1 5 9。 既然如此,何乐而不为呢?如果这样的一条语句是在一个文本文件里,则可以编写汇编 语言程序读取文本文件并把代数表达式转换成机器代码。 如果只计算一次这样的代数表达式,则可以手算或用计算器计算。如果需要用不同的 A、 B、C值来计算表达式的值,则可能需要考虑如何用计算机来计算。正因为如此,代数表达式 不可能单独出现,应该考虑到表达式的上下文,用不同的值代入计算。 现在已开始创建所谓的高级程序设计语言。汇编语言称作低级语言,因为它与计算机硬 件密切相关。尽管“高级”用来描述除汇编语言以外的任何程序设计语言,但这些语言中, 一些语言还比另一些语言更要高级一些。如果你是一家公司的总裁,且坐在计算机前输入 “计算全年的收益和支出,做出年度报表,打印两千份给所有的股东”,那么你确实正在用非 常高级的语言工作。在现实生活中,程序设计语言并没有达到这样理想的境界。 人类语言是千百年来复杂的影响、随机变化和不断适应的结果,即使像世界语这样的人 工语言也来源于现实语言。然而,高级计算机语言是审慎而周密的概念语言。发明程序设计 语言面临的挑战是如何使语言具有吸引力,因为语言定义了人们如何向计算机发送指令。从 2 0世纪5 0年代开始到1 9 9 3年,估计已发明和实现了1 0 0 0多种高级语言。 当然,这还并不足以简单地定义高级语言(它牵涉到语言所采用的语法),还必须有编译 程序用来将高级语言语句转换成机器码。像汇编程序一样,编译程序需要一个字符接一个字 符地读取源代码文件,并分解成短语、符号和数字,但编译程序比汇编程序更复杂。从某种 意义上讲,汇编程序较简单,因为在汇编语言语句与机器码之间有一一对应的关系。编译程 序通常需要把一条高级语言语句转换成许多机器码指令。编译程序不容易编写,许多书中描 述了它们的设计与构造,所以本书不作介绍了。 高级语言有优点也有缺点。最主要的优点是高级语言比汇编语言容易学且容易编写。用 高级语言编写的程序清晰、简明。高级语言通常是可移植的—也就是说,它不像汇编语言 那样依赖于特定的处理器。所以,程序设计员不需要知道程序将要运行其上的机器的内部结 构。当然,如果需要让程序在不止一种处理器上运行,则需要相应的编译程序生成针对这些 处理器的机器码。可执行文件仍然只适用于某一个处理器。 另一方面,差不多都是如此,一个好的汇编语言程序设计员可以写出比编译程序所能产 生的更优化的代码。也就是说,用高级语言编写的程序所产生的可执行文件比用汇编语言编 写功能相同的程序所产生的可执行文件要大,且执行速度较慢。(最近几年,随着微处理器的 日趋复杂以及编译程序在优化代码方面的日趋成熟,这种差别已变得不很明显。 ) 还有,尽管高级语言使得处理器更容易使用,但并没有使它的功能更强大。而使用汇编 语言可以最大限度地利用处理器的能力。因为高级语言需要转换成机器码,所以高级语言只 会降低处理器的能力。如果一个高级语言是真正可移植的,则它不能使用某种处理器的独有 特点。 例如,许多处理器都有移位指令。前面讲过,这些指令把累加器中的位向左或向右移动。 但是,几乎没有高级语言有这样的操作。如果程序中要用到移位,则需要用乘 2或除2操作来 处理(其实,现在许多编译程序都用处理器的移位指令来实现乘或除以 2的幂)。许多高级语 254 编码的奥秘 下载
Chinapub.com 第章高语言和缓语言255 下载 言同样也不包括按位的逻辑运算 早先的家用计算机中,许多应用程序是用汇编语言编写的,而现在除非有特殊需要,汇 编语言已经很少用到。由于已在处理器中添加了一些硬件来实现流水线技术一同时有多个 指令码累进执行——汇编语言则变得更难以掌握。与此冋时,编译程序却逐步走向成熟。现 代计算机的大容量存储能力也在这种趋势——程序设计员不再满足于编制在小的内存和磁盘 上运行的代码一中也扮演着重要角色。 尽管许多早期计算机的设计者都试图用代数符号来闸明他们的观点,但通常认为第一个 真正成功的编译程序是由 Grace Murray Hopper(1906-1992)于1952年在雷明顿为 UNIVAC 而设计的A-0。当 Hoppert博士1944年为 Howard Aiken工作时,就已开始了计算机的早期研究 工作。在她80多岁时,仍然活跃在计算机界,为DEC公司作一些公关工作 今天仍然在使用的最古老的高级语言(尽管这些年中得到了广泛的修改)是 FORTRAN 许多计算机语言的名字都是大写字母,因为它们是由许多单词的首字母构成的。 FORTRAN是 由 FORmula前3个字母和 TRANSlation的前4个字母混合而成,是在20世纪50年代中期由IBM 公司为704系列计算机开发的。多年来, FORTRAN一直被选作为科学和工程的计算语言,它 广泛支持浮点运算甚至支持复数运算。 所有计算机语言都有它们的支持者和批评者,并且人们可能只热衷于他们所喜好的语言。 尽量站在中立的立场上,我选择一种语言作为原型来解释那些差不多再没有人用的程序设计 概念。这种语言的名字是 ALGOL(即 ALGOrithmic Language)。 ALGOL也可用来探索高级程 序设计语言的本质,因为从某种意义上来说它正如一粒种子,成为过去40年来许多流行的通 用语言的直接祖先。甚至在今天,人们也用到“类 ALGOL”的程序设计语言。 它的第一个版本是 ALGOL58,由一个国际委员会在1957~1958年设计而的。两年后,即 1960年进行了修改,修订版命名为 ALGOL60。最后的版本是 ALGOL68。本章用到的 ALGOL版本在文档“ Revised report on the Algorithmic Language ALGOL60”中有描述,该 文档在1962年完成,1963年第1次印刷 让我们来编写一些ALGOL代码。假设一个名为ALGOL.COM的编译程序运行在CPM或 MS-DOS下。第一个 ALGOL程序是一个名为 FIRSTALG的文本文件,注意它的文件类型 个 ALGOL程序必须由 begin和end作为开始和结束,以下为显示一行文本的程序: begin print('This is my fist ALGOL program! ' ende 可以用 ALGOL编译程序来编译 FIRSTALG程序,操作如下: ALGOL FIRSTALG ALGOL编译程序的响应可能是显示类似于下面的内容: Line 3: Unrecognized ke ALGOL对拼写的挑剔不亚于传统的英语教师。在输入程序时若拼错了单词end,编译程 序则会告知程序有一个语法错误。当它碰到ende时,它希望那是它可以识别的关键字 修改了错误以后,可以再运行 ALGOL编译程序。有时,编译程序会直接生成一个可执行 件(名为 FIRST COM,或者是MS-DOS下的 FIRSTEXE):有时,还需要进行另一个步骤。 无论怎样,你都可以从命令行运行 FIRST程序:
言同样也不包括按位的逻辑运算。 早先的家用计算机中,许多应用程序是用汇编语言编写的,而现在除非有特殊需要,汇 编语言已经很少用到。由于已在处理器中添加了一些硬件来实现流水线技术—同时有多个 指令码累进执行—汇编语言则变得更难以掌握。与此同时,编译程序却逐步走向成熟。现 代计算机的大容量存储能力也在这种趋势—程序设计员不再满足于编制在小的内存和磁盘 上运行的代码—中也扮演着重要角色。 尽管许多早期计算机的设计者都试图用代数符号来阐明他们的观点,但通常认为第一个 真正成功的编译程序是由 Grace Murray Hopper(1 9 0 6-1 9 9 2)于1 9 5 2年在雷明顿为U N I VA C 而设计的A - 0。当H o p p e r博士1 9 4 4年为Howard Aiken 工作时,就已开始了计算机的早期研究 工作。在她8 0多岁时,仍然活跃在计算机界,为 D E C公司作一些公关工作。 今天仍然在使用的最古老的高级语言(尽管这些年中得到了广泛的修改)是 F O RT R A N。 许多计算机语言的名字都是大写字母,因为它们是由许多单词的首字母构成的。 F O RT R A N是 由FORmula 前3个字母和T R A N s l a t i o n的前4个字母混合而成,是在 2 0世纪5 0年代中期由I B M 公司为7 0 4系列计算机开发的。多年来, F O RT R A N一直被选作为科学和工程的计算语言,它 广泛支持浮点运算甚至支持复数运算。 所有计算机语言都有它们的支持者和批评者,并且人们可能只热衷于他们所喜好的语言。 尽量站在中立的立场上,我选择一种语言作为原型来解释那些差不多再没有人用的程序设计 概念。这种语言的名字是 A L G O L(即ALGOrithmic Language)。A L G O L也可用来探索高级程 序设计语言的本质,因为从某种意义上来说它正如一粒种子,成为过去 4 0年来许多流行的通 用语言的直接祖先。甚至在今天,人们也用到“类 A L G O L”的程序设计语言。 它的第一个版本是A L G O L 5 8,由一个国际委员会在 1 9 5 7~1 9 5 8年设计而的。两年后,即 1 9 6 0年进行了修改,修订版命名为 ALGOL 60 。最后的版本是 ALGOL 68 。本章用到的 A L G O L版本在文档“Revised Report on the Algorithmic Language ALGOL 60”中有描述,该 文档在1 9 6 2年完成,1 9 6 3年第1次印刷。 让我们来编写一些 A L G O L代码。假设一个名为 A L G O L . C O M的编译程序运行在 C P / M或 M S - D O S下。第一个A L G O L程序是一个名为F I R S T. A L G的文本文件,注意它的文件类型。 一个A L G O L程序必须由b e g i n和e n d作为开始和结束,以下为显示一行文本的程序: begin print('This is my fist ALGOL program!'); ende 可以用A L G O L编译程序来编译F I R S T.ALG 程序,操作如下: ALGOL FIRST.ALG A L G O L编译程序的响应可能是显示类似于下面的内容: Line 3: Unrecognized keyword 'ende'. A L G O L对拼写的挑剔不亚于传统的英语教师。在输入程序时若拼错了单词 e n d,编译程 序则会告知程序有一个语法错误。当它碰到 e n d e时,它希望那是它可以识别的关键字。 修改了错误以后,可以再运行 A L G O L编译程序。有时,编译程序会直接生成一个可执行 文件(名为F I R S T. C O M,或者是M S - D O S下的F I R S T. E X E);有时,还需要进行另一个步骤。 无论怎样,你都可以从命令行运行 F I R S T程序: 第24章 高级语言和低级语言 255 下载
256 编码的奥秘 Chinapub. coM FIRST FIRST程序的响应是显示: This is my fist ALGOL program! 糟糕!还有一个拼写错误。这是一个编译程序不能发现的错误,因此,称为运行时错误 (run- time error)—即只在运行程序时才出现的错误。 可以看出,在该 ALGOL程序中, print语句在屏幕上显示一些内容,本例是一行文本(因 此,这个 ALGOL程序等效于本章前面CP/M下的汇编程序)。 print语句实际上并不是 ALGOL 语言正式定义的一部分,这里只假设正在用的这个 ALGOL编译程序包含有这样一个实用工具 有时称作内部函数。 print语句——就像许多 ALGOL语句(除 begin和end外)一样—后面必 须跟引号。 print语句向里缩进不是必须的,只不过使得程序结构更清晰 假设要编写一个程序计算两个数的乘法。每一个程序设计语言都有变量这个概念。在程 序中,变量名可以为一个字母、一个短的字母序列,甚至为一个短词。实际上,变量对应于 一个内存单元,但在程序中是通过名字来引用的,并不是通过内存地址。下面这个程序有3个 变量,名为a、b和c begin b a:=535.43; b:=289.771 c:=a×b print The product of and real语句是说明语句,用来表明程序中要说明的变量。本例中,变量a、b、c是实数或浮 点数( ALGOL也支持关键字 Integer,用来说明整型变量)。通常,程序设计语言要求变量名 以字母开头。只要第一个字符是字母,变量名可以包含数字,但不能包含空格及许多其他字 符。通常编译程序要限制变量名的长度。本章的例子都采用一个字母作为变量名。 如果使用的 ALGOL编译程序支持IEEE浮点数标准,则程序中的3个变量都需要4个字节的 存储空间(对单精度数)或8个字节的存储空间(对双精度数)。 接下来的三个语句是赋值语句。在 ALGOL中,赋值语句定义为冒号后紧跟等号。(在许 多计算机语言中,赋值语句只需用等号。)赋值语句的左边是变量,右边是表达式。前两个赋 值语句是给a和b赋给一个值,第三个赋值语句中变量c的值由变量a和b产生 今天,在程序设计语言中,大家熟悉的×(乘号)通常不允许使用,因为它不属于ASCI 码和 EBCDIC的字符集。许多程序设计语言用星号(*)表示乘法。虽然 ALGOL用斜杠(/) 表示除法,但也包括一个除号(÷)表示整数除法,即表明被除数中有多少倍的除数 ALGOL中也定义了箭头(↑),这是另一个非ASCI码字符,用来表示乘方 最后是用来显示的 print语句。本例中即有文本又有变量,它们用逗号隔开。显示ASCI字 符可能并不是 print语句的主要工作,本例中,它的功能还包括把浮点数转换成ASC码 The product of 535.43 and 289. 711 is 155152.08653 接着程序终止,返回到操作系统 如果想乘另外两个数,则需要修改程序,改变数,重新编译,再运行。可以利用一个名 为read的内置函数来避免这种频繁的重新编译工作:
FIRST F I R S T程序的响应是显示: This is my fist ALGOL program! 糟糕!还有一个拼写错误。这是一个编译程序不能发现的错误,因此,称为运行时错误 (run-time error)—即只在运行程序时才出现的错误。 可以看出,在该A L G O L程序中,p r i n t语句在屏幕上显示一些内容,本例是一行文本(因 此,这个A L G O L程序等效于本章前面 C P / M下的汇编程序)。p r i n t语句实际上并不是 A L G O L 语言正式定义的一部分,这里只假设正在用的这个ALGOL 编译程序包含有这样一个实用工具, 有时称作内部函数。p r i n t语句—就像许多ALGOL 语句(除b e g i n和e n d外)一样—后面必 须跟引号。p r i n t语句向里缩进不是必须的,只不过使得程序结构更清晰。 假设要编写一个程序计算两个数的乘法。每一个程序设计语言都有变量这个概念。在程 序中,变量名可以为一个字母、一个短的字母序列,甚至为一个短词。实际上,变量对应于 一个内存单元,但在程序中是通过名字来引用的,并不是通过内存地址。下面这个程序有 3个 变量,名为a、b和c: begin real a,b,c; a:=535.43; b:=289.771; c:=a×b; print ('The product of ', a, ' and ' , b, ' is ', c); end real 语句是说明语句,用来表明程序中要说明的变量。本例中,变量 a、b、c是实数或浮 点数(A L G O L也支持关键字 i n t e g e r,用来说明整型变量)。通常,程序设计语言要求变量名 以字母开头。只要第一个字符是字母,变量名可以包含数字,但不能包含空格及许多其他字 符。通常编译程序要限制变量名的长度。本章的例子都采用一个字母作为变量名。 如果使用的A L G O L编译程序支持I E E E浮点数标准,则程序中的 3个变量都需要4个字节的 存储空间(对单精度数)或 8个字节的存储空间(对双精度数)。 接下来的三个语句是赋值语句。在 A L G O L中,赋值语句定义为冒号后紧跟等号。(在许 多计算机语言中,赋值语句只需用等号。)赋值语句的左边是变量,右边是表达式。前两个赋 值语句是给a和b赋给一个值,第三个赋值语句中变量 c的值由变量a和b产生。 今天,在程序设计语言中,大家熟悉的×(乘号)通常不允许使用,因为它不属于 A S C I I 码和E B C D I C的字符集。许多程序设计语言用星号( *)表示乘法。虽然 A L G O L用斜杠(/) 表示除法,但也包括一个除号(÷)表示整数除法,即表明被除数中有多少倍的除数。 A L G O L中也定义了箭头(↑),这是另一个非A S C I I码字符,用来表示乘方。 最后是用来显示的p r i n t语句。本例中即有文本又有变量,它们用逗号隔开。显示 A S C I I字 符可能并不是p r i n t语句的主要工作,本例中,它的功能还包括把浮点数转换成 A S C I I码: The product of 535.43 and 289.711 is 155152.08653 接着程序终止,返回到操作系统。 如果想乘另外两个数,则需要修改程序,改变数,重新编译,再运行。可以利用一个名 为r e a d的内置函数来避免这种频繁的重新编译工作: 256 编码的奥秘 下载
Chinapub.com 章高语言和缓语言257 下载 begin real a, b,c print ('Enter the first number: print ('Enter the second number: ' read (b) c:=a×b print The product of IS c) end read语句从键盘读入ASCI码字符并转换成浮点数 高级语言中一个非常重要的结构是循环。循环使得同一段程序依据一个变量的多个不同 的值来运行。假设有一段程序用来计算3、5、7和9的立方,就可以这样做 begin begin print The cube of for语句设置变量a的初值为3,然后执行do关键字以后的语句。如果要执行的语句不止一条 (本例中正是如此),则这些语句必须包括在 begin和end之间,这两个关键字定义了一个语句 块。for语句接着把变量a设置成5、7和9,并执行这些相同的语句 下面是for语句的另一种形式,它计算3~99间奇数的立方值 begin for a :=3 step 2 until 99 do begin b axaX print ('Th ube of for语句设置变量a的初值为3,然后执行for语句后的语句块。然后a以step关键字后面的值2为 步长增加,得到新值5,并用来执行代码块。变量a不断加2,当它超过99时,for循环结束 程序设计语言通常都有非常严格的语法。例如,在 ALGOL60中,关键字for后只能跟 种类型的东西,即变量名。而在英语里,单词for后可以跟许多不同的单词,如“ for example” 虽然编译程序不是容易编写的简单程序,但它显然要比解释人类语言的程序要简单得多了。 大多数程序设计语言的另一个重要特性是包含条件语句。条件语句只是在某个条件为真 时才允许执行另一条语句。下面是使用 ALGOL内部函数sqrt的一个例子,用来计算平方根 qrt函数不能用来处理负数,所以程序中应避免出现这种情况:
begin real a,b,c; print ('Enter the first number: '); read (a); print ('Enter the second number: '); read (b); c:= a×b; print ('The product of ', a, ' and ', b, ' is ', c); end r e a d语句从键盘读入A S C I I码字符并转换成浮点数。 高级语言中一个非常重要的结构是循环。循环使得同一段程序依据一个变量的多个不同 的值来运行。假设有一段程序用来计算 3、5、7和9的立方,就可以这样做: begin real a, b; for a := 3, 5, 7, 9 do begin b := a× a× a; print (' The cube of ', a, ' is ', b); end end f o r语句设置变量 a的初值为 3,然后执行 d o关键字以后的语句。如果要执行的语句不止一条 (本例中正是如此),则这些语句必须包括在 b e g i n和e n d之间,这两个关键字定义了一个语句 块。f o r语句接着把变量a设置成5、7和9,并执行这些相同的语句。 下面是f o r语句的另一种形式,它计算 3~9 9间奇数的立方值: begin real a, b; for a :=3 step 2 until 99 do begin b := a× a× a; print ('The cube of ', a, ' is ' , b); end end f o r语句设置变量a 的初值为3,然后执行f o r语句后的语句块。然后 a以s t e p关键字后面的值2为 步长增加,得到新值5,并用来执行代码块。变量 a不断加2,当它超过9 9时,f o r循环结束。 程序设计语言通常都有非常严格的语法。例如,在 ALGOL 60中,关键字f o r后只能跟一 种类型的东西,即变量名。而在英语里,单词f o r后可以跟许多不同的单词,如“for example”。 虽然编译程序不是容易编写的简单程序,但它显然要比解释人类语言的程序要简单得多了。 大多数程序设计语言的另一个重要特性是包含条件语句。条件语句只是在某个条件为真 时才允许执行另一条语句。下面是使用 A L G O L内部函数s q r t的一个例子,用来计算平方根。 s q r t函数不能用来处理负数,所以程序中应避免出现这种情况: 第24章 高级语言和低级语言 257 下载
258编的奥 begin real a, b print ('Enter a number: ')i if a< o then print ('Sorry, the number was negative. else print ('The square root of ',a, ,b) 左尖括号<是小于号。如果用户输入的一个数小于0,则执行第一个prin语句。否则,该数大 于等于0,则执行包含另一个 print语句的语句块。 到目前为此,本章程序中的每个变量只能存放一个值。用一个变量来存放多个值也是很 方便的,这就是数组。 ALGOL程序中声明一个数组的方法如下所示: eal array a[1: 1001 本例中,表明要用该变量来存储100个不同的浮点值,这些值称作数组元素。第一个为 a[1],第二个为a[2],最后一个为a100]。方括号中的数字称作数组下标 下例程序计算从1~100的所有数的平方根,把结果存放在数组中并显示出来 real array a[1: 100]i integer 1 step 1 until 100 pr⊥nt square root of,i a[i]); 程序中也声明了一个整型变量,名为i(因为它是 Integer的第一个字母,所以经常用来作 为整型变量名)。在第一个for循环中,数组的每一个元素赋值为它的下标的平方根;第二个 for循环中,输出这些值。 除了实型和整型外,变量还可以声明为布尔型(为了纪念第10章提到的乔治·布尔) 个布尔变量只有两个可能的值,即true和 False。本章的最后一个程序里将用到布尔数组(和到 目前为止学到的几乎所有特性)。该程序实现称为“ Eratosthenes漏勺”的用来找到素数的著 名算法。 Eratosthenes(大约公元前276-196年)是亚历山大传说中的图书馆的管理员,他由 于精确地计算出了地球的圆周长而名垂史册。 素数是指只能被1和它本身整除的自然数。第一个素数是2(唯一的偶数素数),此外,素 数还有3、5、7、11、13、17等等 Eratosthenes方法是从以2开始的正的自然数列表开始。因为2是素数,则要删除所有是2
begin real a, b; print ('Enter a number: '); read (a); if a< 0 then print ('Sorry, the number was negative.'); else begin b = sqrt (a); print ('The square root of ', a, 'is ', b); end end 左尖括号<是小于号。如果用户输入的一个数小于 0,则执行第一个p r i n t语句。否则,该数大 于等于0,则执行包含另一个p r i n t语句的语句块。 到目前为此,本章程序中的每个变量只能存放一个值。用一个变量来存放多个值也是很 方便的,这就是数组。A L G O L程序中声明一个数组的方法如下所示: real array a[1:100]; 本例中,表明要用该变量来存储 1 0 0个不同的浮点值,这些值称作数组元素。第一个为 a [ 1 ],第二个为a [ 2 ],最后一个为a [ 1 0 0 ]。方括号中的数字称作数组下标。 下例程序计算从1~1 0 0的所有数的平方根,把结果存放在数组中并显示出来: begin real array a[1:100]; integer i; for i :=1 step 1 until 100 do a[i] := sqrt(i); for i :=1 step 1 until 100 do print ('The square root of ', i, ' is ', a[i]); end 程序中也声明了一个整型变量,名为 i(因为它是i n t e g e r的第一个字母,所以经常用来作 为整型变量名)。在第一个for 循环中,数组的每一个元素赋值为它的下标的平方根;第二个 f o r循环中,输出这些值。 除了实型和整型外,变量还可以声明为布尔型(为了纪念第 1 0章提到的乔治·布尔)。一 个布尔变量只有两个可能的值,即 t r u e和f a l s e。本章的最后一个程序里将用到布尔数组(和到 目前为止学到的几乎所有特性)。该程序实现称为“ E r a t o s t h e n e s漏勺”的用来找到素数的著 名算法。E r a t o s t h e n e s(大约公元前2 7 6-1 9 6年)是亚历山大传说中的图书馆的管理员,他由 于精确地计算出了地球的圆周长而名垂史册。 素数是指只能被1和它本身整除的自然数。第一个素数是 2(唯一的偶数素数),此外,素 数还有3、5、7、11、1 3、1 7等等。 E r a t o s t h e n e s方法是从以 2开始的正的自然数列表开始。因为 2是素数,则要删除所有是 2 258 编码的奥秘 下载
inapub.com 4章高语言和级语言259 下载 的倍数的数(即除2以外的所有偶数),这些数都不是素数。因为3是素数,则要删除所有是3 的倍数的数。已经知道4不是素数,因为它已被删除了。下一个素数是5,则要删除所有是5的 倍数的数。依此类推,那些余下的数就是素数。 下面的 ALGOL程序用来确定2~10000的所有素数,通过声明一个布尔数组来标识从2 10000的所有数来实现该算法 begin Boolean array a[2: 10000]; for 1:=2 step 1 until 10000 do a[i: = true; for 1: =2 step 1 until 100 do if a[i a[i×j alse for i =2 step 1 until 10000 do if a[i] then print (i)i 第一个for循环把数组所有元素的布尔值设置为true。这样,程序一开始假设所有的数都是素 数。第二个for循环从1~100(为10000的平方根)。如果数是素数,意味着a[订为真,则另 for循环用来把该数的倍数设置为 false,这些数都不是素数。最后一个for循环输出所有的素 数,即a[为真时对应的i值。 有时人们在争论程序设计到底是一门艺术还是一门科学。一方面需要在大学里学习有关计 算机科学的课程,另一方面又要看著名的如 Donald Knuth的《 The Art of Computer Programmign》 系列这样的书。物理学家 Richard Feynman写道“更确切的说,计算机科学更像工程一—都是 用一些东西来实现另一些东西” 如果让100个不同的人都来编写输出素数的程序,将会得到100个不同的方法。即使这些 程序员都有“ Eratosthenes漏勺”这种思想,也不会正好以同样的方法实现。如果程序设计真 的是一门科学,就不会有如此多的方法,而不正确的解决方法也是经常有的。偶尔程序设计 问题会激起富有创造性和敏锐观察力的火花,而这就是“艺术”的成分。但是,程序设计更 多的是设计和组装的过程,就像在架设一座大桥。 早期的许多程序设计员都是科学家和工程师,他们利用 FORTRAN和 ALGOL所要求的数 学算法来阐述自己的问题。然而,纵观程序设计语言的历史可以发现,人们希望有能被更大 范围的人们所使用的语言。 第一个为商务系统设计的成功语言是 COBOL( common business oriented language),今天 仍被广泛使用。由美国工业和国防部组成的委员会于1959年早期推出了 COBOL,它受到了 Grace Hopper的早期编译程序的影响。从某种意义上说, COBOL使得管理人员一—可能并不 具体设计编码一至少可以看懂程序代码并且能够检查代码是否按所预定的去工作(在现实 生活中,这种情况很少发生) COBOL广泛支持记录和生成报表。记录是按照一致方式组织的信息的集合体,例如:保
第24章 高级语言和低级语言 259 下载 的倍数的数(即除 2以外的所有偶数),这些数都不是素数。因为 3是素数,则要删除所有是 3 的倍数的数。已经知道 4不是素数,因为它已被删除了。下一个素数是 5,则要删除所有是5的 倍数的数。依此类推,那些余下的数就是素数。 下面的A L G O L程序用来确定2~10 000的所有素数,通过声明一个布尔数组来标识从 2 ~ 1 0 0 0 0的所有数来实现该算法: begin Boolean array a[2:10000]; integer i, j for i :=2 step 1 until 10000 do a[i] := true; for i :=2 step 1 until 100 do if a[i] then for j := 2 step 1 until 10000 ÷ i do a [i × j] := false; for i := 2 step 1 until 10000 do if a[i] then print (i); end 第一个f o r循环把数组所有元素的布尔值设置为 t r u e。这样,程序一开始假设所有的数都是素 数。第二个f o r循环从1~1 0 0(为10 000的平方根)。如果数是素数,意味着 a [ i ]为真,则另一 个f o r循环用来把该数的倍数设置为 f a l s e,这些数都不是素数。最后一个 f o r循环输出所有的素 数,即a [ i ]为真时对应的i值。 有时人们在争论程序设计到底是一门艺术还是一门科学。一方面需要在大学里学习有关计 算机科学的课程,另一方面又要看著名的如Donald Knuth的《The Art of Computer Programmign》 系列这样的书。物理学家 Richard Feynman写道“更确切的说,计算机科学更像工程—都是 用一些东西来实现另一些东西”。 如果让1 0 0个不同的人都来编写输出素数的程序,将会得到 1 0 0个不同的方法。即使这些 程序员都有“ E r a t o s t h e n s漏勺”这种思想,也不会正好以同样的方法实现。如果程序设计真 的是一门科学,就不会有如此多的方法,而不正确的解决方法也是经常有的。偶尔程序设计 问题会激起富有创造性和敏锐观察力的火花,而这就是“艺术”的成分。但是,程序设计更 多的是设计和组装的过程,就像在架设一座大桥。 早期的许多程序设计员都是科学家和工程师,他们利用 F O RT R A N和A L G O L所要求的数 学算法来阐述自己的问题。然而,纵观程序设计语言的历史可以发现,人们希望有能被更大 范围的人们所使用的语言。 第一个为商务系统设计的成功语言是 C O B O L(common business oriented language),今天 仍被广泛使用。由美国工业和国防部组成的委员会于 1 9 5 9年早期推出了 C O B O L,它受到了 Grace Hopper的早期编译程序的影响。从某种意义上说, C O B O L使得管理人员—可能并不 具体设计编码—至少可以看懂程序代码并且能够检查代码是否按所预定的去工作(在现实 生活中,这种情况很少发生)。 C O B O L广泛支持记录和生成报表。记录是按照一致方式组织的信息的集合体,例如:保
260 编码的奥秘 Cina°bu60M 下载 险公司可能要维持包含有它所卖的所有险种的一个大文件,每一险种为一单独记录,包括客 户姓名、出生日期和其他信息。早期的许多 COBOL程序设计成能处理存储在IBM穿孔卡片上 的80列记录,为了尽可能少地占用卡片空间,日期中的年份通常用2位编码而不是4位,这导 致了随着2000年的到来而普遍出现的“千年虫”问题。 20世纪60年代中期,伴随着 System/360项目的开发,IBM公司开发了名为PL的程序设计 语言(I是罗马数字1,PL/表示 programming language number one)。PLⅠ试图把 ALGOL的块 结构、 FORTRAN的科学和数学计算功能以及 COBOL的记录和报表能力结合起来。但是,它 却远没有像 FORTRAN和 COBOL那样流行。 尽管 FORTRAN、 ALGOL、 COBOL和PL/都有适用于家用计算机的版本,但是它们都不 具备 BASIC所具备的那种对小计算机的影响力 BASIC( beginner'sl- purpose symbolic instruction code)是 Dartmouth数学系的John Kemeny和 Thomas Kurtz在1964年为 Dartmouth的分时系统开发的。 Dartmouth的许多学生并非 主修数学或工程课程,所以他们不能在穿孔卡片和很难的程序设计语法上花费很多时间。 Dartmouth的学生坐在终端前,只需在数字之后简单地敲入 BASIC语句,即可建立 BASIC程序。 数字表明程序中语句的顺序。没有数字在前的语句是对系统的命令,如SAVE(存储 BASIC程 序到磁盘)、LIST(按顺序显示行)和RUN(编译和执行程序)。第一批印刷的 BASIC指令手 册中的第一个 BASIC程序为 10LETx=(7+8)/3 20 PRINT X 不同于 ALGOL, BASIC不需要程序设计员来指定一个变量是按整数存储还是浮点数存储。 不需要程序员操心,大多数数都是按浮点数存储 许多后来的 BASIC版本是解释程序而不是编译程序的。前面讲过,编译程序是读取一个 源文件,并产生一个可执行文件:而解释程序读取源代码并在读的过程中直接执行而不生成 可执行文件。解释程序比编译程序容易编写,但是,解释程序的执行时间却比编译程序的执 行时间要慢。当比尔·盖茨(生于1955年)和他的密友保罗·艾伦(生于1953年)在1975年 为 Altair8800编写 BASIC解释程序并创立他们的公司——微软公司的时候, BASIC才开始应用 到家用计算机中。 Pascal程序设计语言继承了 ALGOL的许多结构,但也包括了 COBOL的记录处理程序。该 语言由瑞士计算机科学教授 Niklaus wirth(生于1934年)在20世纪60年代后期设计而成。 Pascal在 IBM PC程序设计员中很受欢迎,但却以一种特殊的形式— Turbo Pasca这种产品形 式流行。该产品于1983年由 Borland公司推出,售价为$4995。 Turbo Pascal(由丹麦学生 Anders Hejlsberg(生于1960年)编写)是 Pascal的一个版本,提供了完整的集成化开发环境 文本编辑器和编译程序集成在一个程序里,促进了快速编程。集成化开发环境在大型机上很 流行,但 Turbo Pascal却首先在小机器上实现了 Pasca对Ada有很大影响。Ada是为美国国防部开发使用的一种语言,是以 Augusta Ada Byron命名的。第18章中已提到过这个人,他是查尔斯·巴贝芝的解析机的见证人。 然后就有了C语言,一种受到万般宠爱的程序设计语言。它于1969年~1973年产生,大部 分是由贝尔电话实验室的 Dennis m. ritchie完成的。人们常常问为什么叫C语言,简单的回答 是它来自于一种早期的语言B,B是BCPL( Basic cPl)的一种简单版本,而BCPL又来自于
260 编码的奥秘 下载 险公司可能要维持包含有它所卖的所有险种的一个大文件,每一险种为一单独记录,包括客 户姓名、出生日期和其他信息。早期的许多 C O B O L程序设计成能处理存储在 I B M穿孔卡片上 的8 0列记录,为了尽可能少地占用卡片空间,日期中的年份通常用 2位编码而不是 4位,这导 致了随着2 0 0 0年的到来而普遍出现的“千年虫”问题。 2 0世纪6 0年代中期,伴随着S y s t e m / 3 6 0项目的开发,I B M公司开发了名为P L / I的程序设计 语言(I是罗马数字1,P L / I表示programming language number one)。P L / I试图把A L G O L的块 结构、F O RT R A N的科学和数学计算功能以及 C O B O L的记录和报表能力结合起来。但是,它 却远没有像F O RT R A N和C O B O L那样流行。 尽管F O RT R A N、ALGOL 、C O B O L和P L / I都有适用于家用计算机的版本,但是它们都不 具备B A S I C所具备的那种对小计算机的影响力。 B A S I C(b e g i n n e r’s all-purpose symbolic instruction code)是D a r t m o u t h数学系的J o h n K e m e n y和Thomas Kurtz在1 9 6 4年为D a r t m o u t h的分时系统开发的。 D a r t m o u t h的许多学生并非 主修数学或工程课程,所以他们不能在穿孔卡片和很难的程序设计语法上花费很多时间。 D a r t m o u t h的学生坐在终端前,只需在数字之后简单地敲入 B A S I C语句,即可建立B A S I C程序。 数字表明程序中语句的顺序。没有数字在前的语句是对系统的命令,如 S AV E(存储B A S I C程 序到磁盘)、L I S T(按顺序显示行)和 R U N(编译和执行程序)。第一批印刷的B A S I C指令手 册中的第一个B A S I C程序为: 10 LET X = (7 + 8) / 3 20 PRINT X 30 END 不同于A L G O L,B A S I C不需要程序设计员来指定一个变量是按整数存储还是浮点数存储。 不需要程序员操心,大多数数都是按浮点数存储。 许多后来的B A S I C版本是解释程序而不是编译程序的。前面讲过,编译程序是读取一个 源文件,并产生一个可执行文件;而解释程序读取源代码并在读的过程中直接执行而不生成 可执行文件。解释程序比编译程序容易编写,但是,解释程序的执行时间却比编译程序的执 行时间要慢。当比尔·盖茨(生于 1 9 5 5年)和他的密友保罗·艾伦(生于 1 9 5 3年)在1 9 7 5年 为Altair 8800编写B A S I C解释程序并创立他们的公司—微软公司的时候,B A S I C才开始应用 到家用计算机中。 P a s c a l程序设计语言继承了 A L G O L的许多结构,但也包括了 C O B O L的记录处理程序。该 语言由瑞士计算机科学教授 Niklaus Wi r t h(生于1 9 3 4年)在2 0世纪6 0年代后期设计而成。 P a s c a l在IBM PC程序设计员中很受欢迎,但却以一种特殊的形式—Turbo Pascal这种产品形 式流行。该产品于 1 9 8 3年由B o r l a n d公司推出,售价为 $ 4 9 . 9 5。Turbo Pascal(由丹麦学生 Anders Hejlsberg(生于1 9 6 0年)编写)是P a s c a l的一个版本,提供了完整的集成化开发环境。 文本编辑器和编译程序集成在一个程序里,促进了快速编程。集成化开发环境在大型机上很 流行,但Turbo Pascal却首先在小机器上实现了。 P a s c a l对A d a也有很大影响。A d a是为美国国防部开发使用的一种语言,是以 Augusta Ada B y r o n命名的。第1 8章中已提到过这个人,他是查尔斯·巴贝芝的解析机的见证人。 然后就有了C语言,一种受到万般宠爱的程序设计语言。它于 1 9 6 9年~1 9 7 3年产生,大部 分是由贝尔电话实验室的 Dennis M.Ritchie 完成的。人们常常问为什么叫 C语言,简单的回答 是它来自于一种早期的语言 B,B是B C P L(Basic CPL)的一种简单版本,而 B C P L又来自于
Chinapul.com 第24章高级语言和低级语言 261 下载 CPL(combined programming language 第22章曾提到过UNIⅨX操作系统被设计成可移植的形式。那时许多操作系统都是用汇编语 言针对特定处理器而编写的。1973年,UNX采用C来编写(更确切地说是重写)。从那时起, 操作系统和C语言的关系就开始紧密起来。 C是很简洁的语言,例如, ALGOL和 Pascal中用 begin和end来定义的块,在C语言中用{} 来代替。下面是另一个例子,该例对程序设计员来说是很常见的,就是把一个常量与一个变 量相加: 在C语言中,可以简写为: 如果只需要把变量加1(即增量),甚至可以这样来简写语句 在16位或32位微处理器中,这样一条语句可以由一条机器码指令来实现。 前面曾提到,许多高级语言不包括移位操作和按位逻辑操作,而这些是许多处理器所支 持的操作,C语言是个例外。另外,C语言的另一重要特点是支持指针,指针实质上是数字化 的内存地址。由于C有许多操作类似于常见的处理器指令,因而有时候也把C语言归类于高级 编语言。胜过于任何类 ALGOL语言,C更接近于常用的处理器指令集 然而,所有的类 ALGOL语言—一即指常用的程序设计语言,是在冯·诺依曼计算机体系 结构基础上设计而成的。在设计计算机语言时,突破冯·诺依曼框架并不容易,而让人们来 使用这种语言则更加困难。一个非冯·诺依曼的语言是LISP( LISt Processing),是由John McCarthy在20世纪50年代末设计而成的,可用在人工智能领域。另一个与众不同且与LISP完 全不同的语言是APL( A Programming Language),是由 Kenneth Iverson也在20世纪50年代末 开发而成的。APL采用了一个奇怪的符号集用来一次在整个数字数组上执行操作 虽然类 ALGOL语言仍保持着主导地位,最近几年,出现了叫作面向对象的程序设计语言 使这类语言的地位得到加强。这些面向对象语言与图形化操作系统一起使用,图形化内容在 下一章(即最后一章)将作介绍
C P L(combined programming language)。 第2 2章曾提到过U N I X操作系统被设计成可移植的形式。那时许多操作系统都是用汇编语 言针对特定处理器而编写的。 1 9 7 3年,U N I X采用C来编写(更确切地说是重写)。从那时起, 操作系统和C语言的关系就开始紧密起来。 C 是很简洁的语言,例如,A L G O L和P a s c a l中用b e g i n和end 来定义的块,在C语言中用{} 来代替。下面是另一个例子,该例对程序设计员来说是很常见的,就是把一个常量与一个变 量相加: i =i+5; 在C语言中,可以简写为: i+=5; 如果只需要把变量加1(即增量),甚至可以这样来简写语句: i++; 在1 6位或3 2位微处理器中,这样一条语句可以由一条机器码指令来实现。 前面曾提到,许多高级语言不包括移位操作和按位逻辑操作,而这些是许多处理器所支 持的操作,C语言是个例外。另外, C语言的另一重要特点是支持指针,指针实质上是数字化 的内存地址。由于 C有许多操作类似于常见的处理器指令,因而有时候也把 C语言归类于高级 汇编语言。胜过于任何类A L G O L语言,C更接近于常用的处理器指令集。 然而,所有的类 A L G O L语言—即指常用的程序设计语言,是在冯·诺依曼计算机体系 结构基础上设计而成的。在设计计算机语言时,突破冯·诺依曼框架并不容易,而让人们来 使用这种语言则更加困难。一个非冯·诺依曼的语言是 L I S P(LISt Processing),是由J o h n McCarthy 在2 0世纪5 0年代末设计而成的,可用在人工智能领域。另一个与众不同且与 L I S P完 全不同的语言是A P L(A Programming Language),是由Kenneth Iverson也在2 0世纪5 0年代末 开发而成的。A P L采用了一个奇怪的符号集用来一次在整个数字数组上执行操作。 虽然类A L G O L语言仍保持着主导地位,最近几年,出现了叫作面向对象的程序设计语言, 使这类语言的地位得到加强。这些面向对象语言与图形化操作系统一起使用,图形化内容在 下一章(即最后一章)将作介绍。 第24章 高级语言和低级语言 261 下载