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 编码的奥秘 下载