程 序 设 计 语 言
P ro g ra m m i ng L a ng ua g e
D e s i g n a nd I m pl e m e nt a t i o n
网络教学第 2章 机器体系机构对语言的影响
[学习目标 ],了解程序语言的基本特征;掌握虚拟计算机和绑定时间。
-学习程序设计语言的基本特征;
-了解计算机的硬件结构;
-掌握虚拟计算的基本概念和虚拟计算机的层次;
-掌握编译与解释的基本概念及各自特点;
-掌握绑定时间的基本概念及其与语言实现关系;
[重点和难点 ]:
本章的重点是:虚拟计算机的基本概念;绑定时间的基本概念;编译与解释的基本概念以及各自的特点。
本章的难点是:绑定时间的基本概念机器与语言实现的关系;
[知识点 ]:
计算机的硬件结构;固件计算机;翻译;编译;
解释;虚拟计算机;绑定时间;
概述
早期程序设计语言的设计目标是:使程序能够在价格昂贵的硬件机器上高效运行。因此,尽管当时使用的语言(如 fortran)编程很困难,但它们都拥有高效的转换机制将源程序转换为机器代码。
但如今,计算机的性能价格比不断提高,软件的体系结构发生了重大变化,软件的成本越来越变得昂贵,因此现在程序设计强调程序设计的正确性、可读性和可维护性。
可见软件的体系结构对语言的设计也起到重要的作用,主要表现在两个方面:程序将在那种计算机上运行;实际的硬件所支持的程序执行模型或虚拟机。
2.1 计算机的操作
2.2 虚拟计算机和绑定时间第 2章 机器体系机构对语言的影响
2.1 计算机的操作
一台计算机是一个可以执行算法和存储数据的有机整体。一台计算机 *包含六个主要组成部分,并与程序设计语言组成部分紧密对应,它们分别是:
– 数据:计算机提供的基本数据元素和数据结构。
– 基本操作:计算机对数据实施的基本动作。
– 顺序控制:控制操作执行顺序的机制。
– 数据存取:对每次操作执行所需数据的存取控制机制。
– 存储机制:计算机提供的存储分配机制。
– 操作环境:支持程序和外部环境通信的机制。
注:这六个部分也是设计程序语言的六个基本特征。
*:此处所讲得的计算机可以是物理硬件设备,也可以是通过软件模拟的计算机。
本节主要内容
计算机的硬件结构
固件计算机
翻译器和软件模拟计算机计算机的硬件结构外部存储 ( SM )
及 I / O 设备主存 (M M )
高速缓冲存储器
(c a c h e )
程序地址寄存器
(A R)
数据寄存器 (D R)
解释器 基本操作 1 基本操作 k
CP U
数据
数据在程序执行过程中需要存储,从图可见,
主要有四个存储部件:主存 ( MM) 高速缓存
( Cache),高速寄存器 ( R) 和外部辅助存储器 ( SM) 。这些存储部件的性能不同,存储数据的特点有异。
计算机由一些内部 数据类型 可被硬件直接操作,
包括正型数据、单精度实数、固定长度字符串和位串。
其实,程序在某种意义上也是一种数据,其计算机的内部表示方法是机器语言。
操作
每台计算机都有一个内部基本操作集与机器语言指令相对应。
一个典型的操作集包括与内部数据类型相关的基本算术指令(即整数和实数的加、减、乘、
除法指令),测试指令(如判断 0,判断正、
负数的指令),数据存取操作指令、控制 I/O
指令以及执行顺序控制指令等。
顺序控制
在机器语言程序中,下一条要执行的指令通常由程序地址寄存器 (AR)的内容确定,为了将控制转移到程序某处,必须提供修改 AR内容的基本操作。而最终控制程序执行顺序的是解释器。解释器是计算机操作的核心。如图所示。
取下一条指令解码指令
(确定操作符和操作数)
取指定的操作数分支到指定的操作执行基本操作1
执行基本操作1
执行基本操作1
执行停机操作终止程序的解释和执行数据存取
一般,一条机器指令的格式是:操作码 +操作数域,如 ADD AX,[8012H].
一般操作数存储在寄存器 R或主存储 MM中。
计算机必须提供一个指定和获取操作数的机制。
同样,处理(计算)的结果也必须存储在某个地址单元中。
存储管理
主存 MM、辅助存储器 SM与 CPU的速率相差很大。如 CPU每次操作的时间一般是 纳秒 (ns)级,
MM的 存取速率是 微秒 (us)级,而 SM的 存取速率是毫秒 (ms)级,为了对速率进行平衡,需要采用不同的存取管理 机制 。
为了平衡 CPU与 SM之间 的速率矛盾,OS通常使用多道程序设计技术。
为了 平衡 CPU与 MM之间 的速率矛盾,通常使用 高速缓存 cache。
操作环境
计算机的操作环境包括外围存储器和 I/O设备。
这些外部设备构成了计算机的外部世界,任何同计算机的通信必须通过操作环境进行。不同的外部操作 设备 具有不同的通信速率,如高速存储器(扩充存储器),中速存储器 ( CD-
ROM),低速存储器(磁带),I/O设备(键盘、显示器、打印机、数据通信线路等),因此,程序设计语言必须提供不同的通信机制。
返回本节固件计算机
前面,我们将计算机定义为能够存储和执行程序的数据结构和算法的集合,计算机内执行的程序是以机器语言编写的。
我们一般认为机器语言是低级语言,然而,实际上,任何一种语言 (如 C,java) 都可以作为机器语言,只要精确的定义其算法和数据结构。
即任何一台精确定义的计算机都可以完全使用硬件或软件来实现。理论和逻辑上,硬件和软件具有统一性,即硬件上能够实现的使用软件肯定也能实现,反之亦然。但现实中由于成本及其他实现技术问题。很少采用纯硬件和纯软件实现。
固件计算机是一个相对较为严格的硬件实现方式。即在一台可进行微编程的硬件计算机上通过微程序模拟实现。该计算机的机器语言包括一个低级微指令集,它们 规定了 MM和 cache间,
各 R间通过加法器或乘法器的数据传送。微程序在可编程的主机上模拟计算机操作。微程序通常存储在主机的一个 特殊 的 ROM中,并由主机硬件高速运行。
计算机的微程序模拟也称之为仿真。由于计算机是使用微程序模拟的,并不实际存在,因此仿真计算机也称之为模拟计算机。
返回本节翻译器和软件模拟计算机
如前所述,理论上,可以设计一种硬件或固件计算机来直接执行某种语言(如 C语言)编写的程序,但现实中仍然使用具有低级机器语言的实际计算机,why?
– 成本、速度、灵活性
高级语言在具有低级机器语言的实际计算机上如何运行?
– 解决方案:
翻译(编译);
软件模拟(软件解释);
翻译(编译)
翻译的过程是:将用高级语言编写的源程序转换成实际计算机上等价的机器语言程序(目标程序)。从而,计算机上的硬件可以直接运行目标程序。翻译是由翻译程序完成的,翻译程序将源程序作为输入,输出结果是功能等价的目标语言程序。
典型的翻译器:
– 汇编器( assembler):汇编语言源程序 — > 机器语言目标程序;
– 编译器( compiler):高级语言源程序 — > 与实际计算机可运行的机器语言相近的目标程序。如,
C源程序 —— >汇编语言程序 —— >机器语言程序
(经编译) (经汇编)
– 装入或连接器( loader or linker):将各个分别编译的子程序目标程序装入到内存中适当的地址(重定向),
并将各个子程序连接在一起构成一个地址相容的单一可执行程序,如下图所示:
子程序 编译后的地址 执行地址(重定向地址)
P 0~999 1000~1999
Q 0~1999 2000~3999
库函数 0~3999 4000~7999
– 预处理器 ( preprocessor) 或宏处理器 ( macroprocessor),
高级语言源程序 — >相同语言的标准形式。如 C语言。
注:通常将一个高级语言源程序翻译成一个可在机器上直接运行的机器语言目标程序不是一个翻译过程可完成的,可能需要经过一系列的处理和翻译。如 C++源程序 —— >C语言程序 —— >汇编语言程序 —
— >机器语言程序(可执行的目标语言程序)
软件模拟(软件解释)
通过使用一台主机上运行的程序来模拟一台机器语言是高级语言的计算机的执行。即使用主机上的机器语言来构造一组程序软件(模拟软件或解释软件)来模拟或解释运行用高级语言编写的程序所需要的算法和数据结构。
模拟程序所执行的解释算法类似于,程序解释与执行图,,其功能是以一定的顺序执行所输入的程序的每条指令,并产生程序规定的输出。
此时,我们称主机创造了一个高级语言的虚拟机。主机执行时,我们无法分辨它是直接在硬件上执行还是转换成机器语言后再执行。
翻译与解释之比较
相同点:二者都接受高级语言作为输入。
不同点:
– 功能不同:翻译将源程序 — >等价的目标语言程序;
解释直接执行源程序(用户角度看)。
– 顺序控制:翻译遵循输入的物理序列语句;解释遵循程序的逻辑控制流程。
– 执行次数:翻译对每条语句只处理一次;解释则可能对同一条语句反复解释处理(如循环),也可能完全忽略一些语句(如控制流不能到达的语句)。
– 信息完整性:翻译可能造成源程序信息丢失,调试、
测试较为困难;解释不会。
– 代价:翻译需要耗费更大的存储空间;解释需要较长的执行时间(解码 时间)。
由此可见,翻译与解释各有利弊,且是两个极端。除汇编和 OS中的控制语言及交互式语言之外,在现实中,通常将二者结合。
典型的二者结合的语言实现结构如图所示。
二者的结合翻译器(软件)
连接程序运行时支持库翻译器(软件)
解释器 (固件、
硬件或软件)
操作 (固件、硬件或软件)
虚拟计算机 (完全或部分由软件模拟)
源程序源程序翻译出错信息目标程序可执行程序执行数据输出结果出错信息翻译 装载 执行典型的语言实现结构语言的实现
编译型语言
– 源程序在执行之前需先转换成目标机器语言,模拟
(解释)被限制为只是提供一个函数库。翻译型语言的 翻译 器相对较为复杂和庞大,其侧重点是产生尽可能高效运行的目标代码。如 C,C++,Pascal,Fortran,
Ada等。
解释型语言
– 不产生目标机器代码,只是产生更易于执行的中间代码,由软件解释执行。解释型语言通常执行效率较低,
但翻译速度较快。解释型语言的翻译器较为简单,语言实现的大部分复杂性在于模拟软件。如 Java,LISP,
ML,Prolog,Smalltalk等。
返回本节
2.2 虚拟计算机和绑定时间
上一节,我们将一台计算机定义为算法和数据结构的集合,则一台计算机的实现方式有:
– 通过硬件实现:直接使用物理设备支持算法和数据结构;
– 通过固件实现:使用微程序设计实现支持算法和数据结构;
– 通过软件模拟:构造一种算法和数据结构支持源程序的算法和数据结构;
– 上述方法的综合:直接利用计算机的硬件、
软件和 /或微程序支持。
本节主要内容
虚拟计算机和语言实现
虚拟机的层次
绑定和绑定时间虚拟计算机和语言实现
如果程序设计语言以它们的虚拟计算机来定义,
则每种语言可借助该虚拟计算机来描述语义?
然而,程序设计语言是对每个语法结构给出语义,语言的定义仅仅是隐式的指出了一台虚拟计算机。相同语言在不同的计算机上实现时,
实现者所看到的是不同的虚拟计算机。因此,
同一语言的两个不同的语言实现可能实现了不同的数据结构和操作。
这引出了实现过程中的第一个问题:程序设计语言实现者对语言定义所隐含的虚拟计算机具有不同的理解。
当一种程序设计语言在一台具体的计算机上实现时,实现者首先确定虚拟计算机,然后才考虑构造虚拟计算机。例如,如果要实现整数加法和乘方运算,实现者可考虑由具体计算机提供的加法来实现虚拟计算机的加法运算,而用软件模拟来实现虚拟计算机的乘方运算。如果要实现指示整形变量 X,实现者可以考虑由包含 X值的内存地址直接指示 X,也可以使用指针来指示 X。
这引出了实现过程中的第二个问题:不同具体计算机所提供的不同设施对语言的实现产生差异。
此外,实现者还要考虑在程序的翻译阶段需要完成哪些工作,在程序执行阶段需要做哪些事情。通常在执行时,只有在程序翻译时采用了某些操作建立了运行时间结构后,具体的表示虚拟计算机的数据结构或操作才能够被使用。
如果实现者省略了这些操作以简化翻译器,则数据结构与算法在运行时将会有不同的表示。
这引出了实现过程中的第三个问题:语言实现者关于如何使用具体计算机所提供的设施来模拟虚拟计算机的不同考虑以及为了支持这些虚拟计算机而构造的翻译器存在差异。
返回本节虚拟机的层次 第0 级 硬联逻辑第1 级 微程序控制第2 级 机器语言计算机第3 级 操作系统第4 级 汇编语言计算机第5 级 高级语言计算机第6 级 应用程序硬件维护员逻辑设计员机器语言程序员操作员汇编语言程序员高级语言程序员用户计算机系统典型层次结构实际硬件计算机
(由物理设备实现)
固件虚拟计算机
(由微程序指令控制实现)
机器语言虚拟计算机
(由微程序解释实现)
操作系统虚拟计算机
(由机器语言程序实现)
汇编语言虚拟计算机
(汇编成机器语言实现)
C 语言虚拟计算机
( 与编译后的程序装入运行库实现)
网络虚拟计算机
(用C 或J a v a 语言实现的浏览器)
网络应用虚拟计算机
(用H T M L 网页实现)
网络应用的虚拟机层次结构返回本节绑定和绑定时间
绑定:程序元素与其特性或性质的约束关系。
绑定时间:绑定所发生的时间(翻译或执行)。
绑定和绑定时间可由语言定义或由实现来确定。
绑定时间的分类
执行时(运行时刻)
– 绑定在程序执行时完成。具体包括变量与值以及变量与其存储单元的绑定关系。这种绑定关系存在两种主要子类:
进入时:在进入一个子程序或一个块结构时发生。如在 C
语言中,形式参数与 实际参数的绑定,形式参数与存储单元的绑定在程序执行进入一个子程序时就发生。如
int maxInt(int x,int y) main()
{ if (x<y) maxInt = y; ( int a=5,b=8,maxNum;
else maxInt= x; } maxNum= maxInt(a,b);}
执行时:在程序执行的任何时候发生。如变量与值通过赋值语句产生的绑定。如,int x; x=12;
转换时(编译时)
– 程序设计者选定:程序设计者有意识地选择变量名、
变量的类型和语句结构等在编译时绑定。如变量定义并初始化时,变量与值的绑定,如 char ch=‘a’;
– 翻译程序选定:在没有直接规范的情况下,由翻译程序确定。如 C语言中一个变量与其存储单元的绑定。如
int ary[10];
– 装载程序确定:分别编译的情况下,变量与其存储单元的最终物理存储单元的绑定(重定向),由装载程序确定。如子程序 变量 编译后 P(X)的地址 重定向后 P(X)的地址
P x 0~999 (165) 1000~1999( 1165)
语言实现时:
– 绑定时间一般允许在语言定义中指定。语言设计可以规定一个特别的约束在翻译时间确定,但实际上绑定的时间是由语言的实现所定义的。如,对于
Pascal语言,变量的类型在编译时就已确定,但
Pascal实现 可能在执行时进行类型检查。
语言定义时:
– 语言的大部分结构是在语言定义时确定的。如选择语句的形式、数据结构类型和程序结构通常在语言定义时是固定的。
实例研究
为了进一步说明绑定和绑定时间,我们试考虑如下简单的实例
X=X+10
1) 变量 X的类型集:变量 X一般都有一个类型,
如实型、整型、布尔类型等。 X的类型通常在语言定义时确定,如只有实型、整型、布尔类型、集合类型是允许类型。此时,变量 X的类型集绑定时间是语言定义时。有的语言,如 C,
Java等,允许在程序中自定义类型,则变量 X
的类型集绑定时间是编译时。
2) 变量 X的类型,变量 X的具体类型一般在编译时确定。通常通过在程序中使用显式声明 语句,如 C中的 int X。 一些语言如 Fortran,
Basic语言,程序中的简单变量可以不用显式声明,此时,变量 X的类型只能在程序运行过程中,通过赋给变量 X的值的类型来确定变量 X
的类型,此时,变量 X的具体类型的绑定时间是运行时。如 Basic语言
10 LET X = 12.3
20 LET X = X+10
3) 变量 X可能的值:如果 X的类型是实型,则
X的值就是实数集合中的一个元素,该集合的大小由定义语言的虚拟计算机可以表示和操作的实数确定,它通常是机器硬件上可以方便表示的全体实数。所以,变量 X可能的值的绑定时间是语言定义时。
4) 变量 X的值:在程序执行的任何一点,变量 X都有一个值。如果在定义变量 X时进行了初始化,则编译时就将实际的值与变量 X绑定。
如 int X=12。如果,没有进行初始化,有的语言如 C,在编译时将分配给变量 X的存储单元中的值与 X绑定,有的语言根据变量 X的类型自动进行初始化,如将 X初始化为 0。
在程序运行过程中,通常会根据赋值语句重新改变变量 X与其值的绑定关系。此时,变量 X与其值的绑定时间是运行时。
5)常数 10的表示:在程序文本中,整数 10是使用字符串,10”表示的,而在执行时表示为一个位串序列。在程序文本中,选择 10进制表示法通常是在语言定义时确定的,而在运行时如何表示为一个位串序列是由语言实现时确定的。即常数 10在语言定义时进行了一个绑定,
而在语言实现时,重新进行绑定。
6)操作符,+”的性质:操作符,+”可以是加法操作,也可能是字符串连接操作。这种可能的性质是由语言定义时确定的。即操作符,+”
可能的操作性质的绑定时间是语言定义时。
但操作符,+”的具体操作性质的绑定时简是编译时。一般,编译程序通过操作数的类型来确定,+”的具体操作性质。例如,若变量 X是实型,则,+”被绑定为实数加;若 X是整形,则
,+”被绑定为整数加。
绑定时间的重要性
我们在前面详细讨论了绑定时间,有什么作用?
我们首先比较 Fortran 语言与 ML语言
– 相同点:高级语言;经过编译在虚拟计算机上运行。
– 异同点:
Fortran适合于大型科学数据处理,运行效率高。
ML适合于字符串处理,灵活性好。
Why?
Fortran与 ML绑定时间之比较
Fortran语言中,数组算术运算和字符串等特性的绑定大部分在翻译时一次完成,只有一小部分需要在运行时处理。而在 ML语言中,这些特性的绑定需在执行时完成,为此,ML程序将花费大量的执行时间进行绑定的建立与消除,因此
Fortran的运行效率远高于 ML。
但,在处理字符串方面,由于 Fortran大部分的绑定在翻译时完成,输入数据较为固定,要编写一个与执行环境相关的数据处理程序较为困难。
而对于 ML,串长和变量类型等绑定可以推迟到程序运行时检测到输入数据及其绑定确定之后进行。因此,ML在处理字符串方面的灵活性优于
Fortran.
早绑定与迟绑定概念
早绑定( Early Binding):大部分绑定在程序执行之前,即翻译阶段完成。
迟绑定( Late Binding):大部分绑定推迟到程序执行阶段处理。
绑定时间重要性的结论
绑定时间对于程序设计语言的效率和灵活性起重要的作用。
对于追求效率为主要目标的语言,如 C,
Fortran,Pascal等,通常它们的设计是尽可能进行早绑定。
而追求灵活性为主要目标的语言,如 ML,
LISP,HTML等,大部分采用迟绑定,以便与数据相关。
对于两个兼顾的语言,如 Ada,提供绑定时间选择机制。
绑定时间与语言实现
绑定时间一般允许在语言定义中指定。语言设计可以规定一个特别的约束在翻译时间确定,但实际上绑定的时间是由语言的实现所定义的。如,
对于 Pascal语言,变量的类型在编译时就已确定,
但 Pascal实现可能在执行时进行类型检查。因此,
一个语言的设计虽然指定了程序处理的某一可能的绑定的早期时间,但实际上该语言的任何实现都可以延迟该绑定。如果语言的设计允许在编译时完成绑定,而将绑定延迟到执行完成可能会导致程序运行的低效。通常,语言的实现应在同一时间完成大部分的绑定。
可见,绑定时间与语言的实现密切相关。
本章小节
程序设计语言具有六个基本特征:数据,基本操作,顺序控制,数据存取,存储管理和操作环境。
固件计算机是一台可进行微编程的硬件计算机上通过微程序模拟实现的计算机。
高级语言程序必须经过翻译成目标语言程序才能在目标计算机上运行。可通过编译和软件解释两种途径。
翻译是将用高级语言编写的源程序转换成实际计算机上等价的机器语言程序(目标程序)。
从而,计算机上的硬件可以直接运行目标程序。
翻译是由翻译程序完成的,翻译程序将源程序作为输入,输出结果是功能等价的目标语言程序。
解释是通过使用一台主机上运行的程序来模拟一台机器语言是高级语言的计算机的执行。即使用主机上的机器语言来构造一组程序软件
(模拟软件或解释软件)来模拟或解释运行用高级语言编写的程序所需要的算法和数据结构。
编译与解释的相同点是:二者都接受高级语言作为输入。
编译与解释的不同点是:
– 功能不同:翻译将源程序 — >等价的目标语言程序;
解释直接执行源程序(用户角度看)。
– 顺序控制:翻译遵循输入的物理序列语句;解释遵循程序的逻辑控制流程。
– 执行次数:翻译对每条语句只处理一次;解释则可能对同一条语句反复解释处理(如循环),也可能完全忽略一些语句(如控制流不能到达的语句)。
– 信息完整性:翻译可能造成源程序信息丢失,调试、
测试较为困难;解释不会。
– 代价:翻译需要耗费更大的存储空间;解释需要较长的执行时间(解码 时间)。
虚拟计算机是一个层次性的结构,典型的虚拟计算机可分成 7个层次。下层为上层提供支持和服务。
绑定是指程序元素与其特性或性质的约束关系。
绑定时间是指绑定所发生的时间,主要有翻译或时和执行时。绑定和绑定时间可由语言定义或由实现来确定。
绑定时间对于程序设计语言的效率和灵活性起重要的作用。对于追求效率为主要目标的语言,
通常应尽可能进行早绑定。而追求灵活性为主要目标的语言,应采用迟绑定。对于两个兼顾的语言,应提供绑定时间选择机制。
习题
T1,2,5
补充习题:
1)程序设计语言具有那几个基本特征。
2)什么叫固件计算机,虚拟计算机,绑定,绑定时间。
3)编译和解释的实现原理是什么,各有何特点。
4)请画出虚拟计算机系统的典型层次结构。并简述各个层次是由什么支持实现的。
5)绑定时间可分成哪几个类型。