第1章提到,计算机硬件只能识别和理解机器语言程序,用各种高级语言编写的源程序

第 3 版 · OCR 辅助 · 原书检索 · 文字用于定位,公式与图表请回原页核验 · 本次导入快照

## 第1章提到,计算机硬件只能识别和理解机器语言程序,用各种高级语言编写的源程序
最后都要翻译(汇编、解释或编译)成以指令形式表示的机器语言才能在计算机上执行。一
台计算机能执行的机器指令的集合称为该机的指令集,它是构成程序的基本元素,也是硬件
设计的依据,它衡量机器硬件的功能,反映硬件对软件支持的程度。系统软件直接建立在硬
件支持的指令基础上,系统程序员感觉到的计算机的功能特性和概念性结构就是指令集体
系结构(instruction set architecture,ISA),简称指令系统,因此,ISA设计的好坏直接决定
计算机的性能和成本。
本章介绍指令系统设计中涉及的各个方面,主要有指令格式、操作类型、操作数类型、寻
址方式、操作码编码、指令系统的风格以及程序的机器级表示等。
4.1指令格式设计
4.1.1指令地址码的个数
冯·诺依曼结构计算机采用“存储程序”工作方式。计算机中的程序一旦被启动运行,
必须能自动地逐条从主存取出指令执行。一条指令中必须明显或隐含地包含以下信息。
(1)操作码。指定操作类型,如移位、加、减、乘、除、传送等。
(2)源操作数或其地址。指出一个或多个源操作数或其所在的地址,可以是主(虚)存
地址、寄存器编号或I/O端口,也可在指令中直接给出一个立即数。
(3)结果的地址。结果所存放的地址,可以是存储单元地址、寄存器编号或I/O端口。
(4)下条指令地址。下条指令存放的存储单元地址。
通常,下条指令地址不需在指令中明显给出,而是隐含在PC中。指令按顺序执行时,
只要自动将 PC的值加上指令长度,就可得到下条指令的地址,当遇到转移指令而不按顺序
执行时,需由指令给出转移到的目标地址。
综上所述可知,一条指令由一个操作码和几个地址码构成。根据指令显式给出的地址
个数,指令可分为三地址指令、二地址指令、单地址指令和零地址指令。
三地址指令中的3个地址分别作为双目运算中两个源操作数的地址和一个结果的地
址;二地址指令中给出的两个地址分别存放双目运算中两个操作数,并将其中一个地址作为
结果的地址;对于一地址指令,如果是单目运算(如取反/取负等)指令,则其地址既是操作数


<!-- page: 109 -->

计算机组成与系统结构(第3版)
92
的地址,也是结果的地址,如果是双目运算,则另一个操作数和结果可以默认存放在累加器
中;零地址指令可能本身就无操作数,所以也无须地址码,例如空操作指令、停机指令等,对
于栈型指令,因为操作数默认在栈顶,所以也可以是零地址指令。
4.1.2指令格式设计原则
指令格式的选择应遵循如下几条基本原则。
(1)指令应尽量短。每条指令长度短,使得程序占用存储空间小,降低空间开销。
(2)要有足够的操作码位数。向后兼容使指令操作类型不断增加,因此必须预留足够
的操作码位数。
(3)操作码的编码必须有唯一的解释。操作码最终需送到指令译码器进行译码,因此,
指令操作码要么是一个唯一的合法编码,要么是不合法的0/1序列。当译码器发现是不合
法操作码时,出现“非法指令”异常。
(4)指令长度应是字节的整数倍。指令执行前存放在内存,而内存往往按字节编址,因
此,指令长度为字节的整数倍,便于指令的读取和指令地址的计算。
(5)合理选择地址字段的个数。地址字段个数涉及指令的长度和指令的规整性问题,
它是空间开销和时间开销权衡的结果。
(6)指令应尽量规整。指令的规整性体现在许多方面,如指令长度是否固定、操作码位
数是否固定、地址码格式是否一致、指令字中各字段的划分位置是否一致等。规整的指令格
式会大大简化硬件的实现。
#### 4.2 指令系统设计
在设计指令系统时,必须遵循以下基本原则。
(1)完备性或完整性。指令的操作类型应尽量完备,应能足够编制任何可计算程序。
但是,如果指令系统太复杂,也会给硬件实现增加困难。因此,较复杂的功能可以通过伪指
令实现。
(2)兼容性。在考虑系列机设计实现时,高档机的指令系统应兼容以前低档机的指令
系统,这给软件资源重复利用带来方便。
(3)均匀性。运算指令应能对多种类型的数据进行处理,包括三种整数(字节、字、双
字)和两种浮点数(单精度和双精度浮点数)类型。
(4)可扩充性。操作码字段要预留一定的编码空间,以便需要时进行扩充。
4.2.1基本设计问题
在设计一个指令系统时,需要考虑以下一些基本问题。
(1)操作码的个数、种类、复杂度如何选择?
如果指令系统中共包含4条指令:取数指令(load)、存数指令(store)、自增指令(INC)、
分支指令(BRN),则用这4条指令足以编制任何可计算程序。不过,虽然这4条指令是完备
的,但会导致大多数程序变得很长,既占空间又花时间。


<!-- page: 110 -->

指令系统
(2)运算指令能对哪几种数据类型进行操作?
高级语言源程序中需要对int、short和char等类型的整型数据,以及float,double等浮
点类型数据,甚至是位串、字符串等进行操作,因此指令设计时需要考虑指令能对这些数据
类型进行相应的操作。
(3)采用什么样的指令格式?
规整型指令采用定长指令字和定长操作码,使得取指令、指令译码、指令地址计算等变
得简单,从而能减少时间开销,但是,规整型指令在空间上会增加开销。因此,应根据设计目
标选择采用规整型还是紧凑型指令格式。
(4)通用寄存器的个数、功能、长度等如何规定?
用户进程的指令中能用的寄存器是用户可见寄存器,也称为通用寄存器。通用寄存器
多,则编译器可以尽量多地把高级语言源程序中的变量分配到通用寄存器中,因而减少指令
执行时访问内存的次数,加快程序运行。但是,通用寄存器过多会使寄存器存取延迟变长,
因而影响指令执行速度。此外,还可能使寄存器编码变长,从而使指令长度变长,通用寄存
器多还会增大CPU 成本,占用更多硅片面积。
通用寄存器的功能分配也很重要,例如,要考虑是否要有专门的栈指针寄存器、栈帧指针
寄存器、过程调用的参数寄存器、过程调用的返回参数寄存器、过程调用的返回地址寄存器等。
此外,还要考虑每个寄存器的长度,以及寄存器的设计如何满足多种不同长度的数据类
型。例如,Intel体系结构IA-32中,用寄存器扩展的方式提供了存放8位、16位、32位等多
种长度操作数的寄存器;MIPS等体系结构中采用的是固定寄存器宽度的设计方案,通过提
供不同的指令来区分操作数的长度。
(5)如何设计寻址方式的种类和编码以及各种寻址方式下有效地址如何计算?
寻址方式字段可以和操作码一起编码,由操作码确定每个操作数的寻址方式,例如,
MIPS体系结构由操作码确定指令类型,指令类型确定后,每个操作数的寻址方式就确定
了。寻址方式字段也可单独编码,例如,IA-32指令中有专门的寻址方式字段。
(6)下条指令的地址如何确定?
几乎所有指令系统都通过一个专门的寄存器来存放下条指令的地址,这个寄存器为PC
或指令指针(instruction pointer,IP)。顺序执行时,指令中无须显式地给出下条指令地址,
默认由PC指出。通过将当前PC的值加上本条指令的长度即可得到下条指令地址;转移指
令等可能会改变程序执行顺序,此时,这些指令中必须有相应的地址码和寻址方式来给出下
条指令地址或下条指令地址的计算方式。
当然,指令系统的设计所涉及的远远不限于上述所列问题,在具体设计过程中,还需要
考虑很多细节问题。
4.2.2操作数类型
操作数是指令处理的对象,从高级语言程序所用数据类型来看,指令涉及的基本操作数
类型应该包括以下几类。
(1)指针或地址。指针或主(虚)存地址通常用无符号整数来表示。
(2)数值数据。数值数据主要是带符号整数和浮点数。带符号整数用二进制补码表
示,浮点数大多用IEEE754标准表示。有些指令系统也提供十进制数运算指令,一般用
第4章
93


<!-- page: 111 -->

计算机组成与系统结构(第3版)
94
NBCD码(8421码)表示十进制数。
(3)位、位串、字符和字符串。位和位串数据一般用来表示一些标志、控制和状态等信
息。字符和字符串数据用来表示文本等。
例如,IA-32架构提供的定点数类型有字节、字(16位)、双字(32位)、四字(64位)。对
于整数,有16位、32位、64位三种补码表示的整数和18位压缩 BCD码表示的十进制整数;
对于序数(即地址、指针等),有字节、字或双字长的无符号整数;对于浮点数,有用IEEE754
表示的32位单精度浮点数、64位双精度浮点数和80位扩展精度浮点数。另外,还提供了
专门的近指针类型数据,用于表示不分段存储器的地址,或用来表示段内偏移的32 位有效
地址,以进行分段式存储器的段内访问。
有关以上各类数据的表示、存放和运算已在第2章和第3章中详细介绍。
4.2.3寻址方式
指令不仅要规定所执行的操作,还要给出操作数或操作数地址。操作数可能是一个常
数,或一个简单变量,或是数组和结构中的某个元素,也可能是栈(stack)中的数据,还可能
是外设I/O接口中的状态字或控制字等。从指令的角度来看,操作数存放位置可以是CPU
中的通用寄存器、存储单元和1/O端口。通常把指令中给出的操作数所在存储单元的地址
称为有效地址,存储单元地址可能是主存物理地址,也可能是虚拟地址。若不采用虚拟存储
机制,有效地址就是主存物理地址;若采用虚拟存储机制,则有效地址就是虚拟地址。
指令给出操作数或操作数地址的方式称为寻址方式。地址字段长度直接影响指令长
度,因而指令的地址码要尽量短,但操作数的存放位置又必须灵活,存放空间也应尽量大。
因此,指令系统应能提供灵活的寻址方式,并使用尽量短的地址码访问尽可能大的寻址空
间。此外,为加快指令执行速度,有效地址计算过程也应尽量简单。
常用的寻址方式有以下几种。
1.立即寻址
在指令中直接给出操作数本身,这种操作数称为立即数。
2.直接寻址
OP @间接地址
存储器
指令中给出的地址码是操作数的有效地址,这种地
址称为直接地址或绝对地址。
有效地址
3.间接寻址
指令中给出的地址码是存放操作数有效地址的存
操作数
储单元地址。图4.1所示的是单级间接寻址过程,指令
格式中的@是间接寻址标志,还可有多重间接寻址。
图4.1 单级间接寻址
4.寄存器寻址
寄存器寻址方式也称为寄存器直接寻址方式,其指令中给出的地址码是操作数所在寄
存器的编号。寄存器寻址有以下优点:①寄存器数量远小于存储单元数,故寄存器编号比
存储地址短,因而寄存器寻址方式的指令较短。②操作数已在CPU中,不用访存,因而指
令执行速度快。
5.寄存器间接寻址
指令中给出的地址码是一个寄存器编号,该寄存器中存放的是操作数的有效地址。例


<!-- page: 112 -->

指令系统
如,Intel8086指令“MOV AX,[BX]”中,寄存器 BX内容为有效地址,有效地址处所在的内
容是操作数。寄存器间接寻址指令较短,因为只要给出一个寄存器编号而不必给出有效地
址。地址码长度和寄存器直接寻址方式相同,但由于要访存,所以寄存器间接寻址指令的执
行时间比寄存器直接寻址指令的执行时间更长。
6.变址寻址
变址寻址方式主要用于对线性表之类的数组元素进行访问。采用变址寻址方式时,指
令中的地址码字段 A给出一个基准地址,如数组的起始地址,而数组元素相对于基准地址
的偏移量在指令中明显或隐含地由变址寄存器1给出,这样,变址寄存器I的内容实际上就
相当于数组元素的下标,每个数据元素的有效地址为变址寄存器的内容加基准地址,即操作
数的有效地址 EA=(I)+A。其中(I)表示变址寄存器1的内容。
如果任何一个通用寄存器都可作为变址寄存器,则必须在指令中明确地给出一个通用
寄存器的编号,并标明作为变址寄存器使用;若处理器中有一个专门的变址寄存器,则无须
在指令中明确给出。指令中的地址码字段称为形式地址,
变址器I
存储器
这里的形式地址是基准地址 A,而变址寄存器中存放的是
3
a[0]
-A
偏移量。
a[1]
a[2]
例如,在Intel 8086指令“MOV AL,[SI+1000H]”
中,右边的操作数采用的就是变址寻址方式,其中,SI为
变址寄存器;1000H为形式地址;SI的内容加上1000H 形
成操作数的有效地址。
A+3
a[3]
图 4.2 数组元素的变址寻址
如图 4.2 所示,指令中的地址码 A给定数组在存储器
中的首地址,变址器I中存放的是数组元素的下标。若存
储器按字节编址,且数组元素占1字节,则C语句for(i=0;i<N;i++){x=a[i];⋯}对应
的循环体中,第一次变址寄存器I的值为0,执行取数指令取出a[0]后,寄存器I的内容加
1,第二次执行循环体时,取数指令就能取出a[1],⋯,如此循环,以实现高级语言对应语句
的功能。如果数组元素占4字节,则每次变址寄存器I的内容就应该加4。
某些计算机中还允许变址寻址与间接寻址结合使用。假定指令中给出的变址寄存器为
I,形式地址为A,则先变址寻址后间接寻址时,操作数的有效地址为EA=(A+(I)),称为
前变址;先间接寻址后变址寻址时,则 EA=(A)+(I),称为后变址。
7.相对寻址
如果某指令的操作数的有效地址或转移目标地址位于该指令所在位置的前、后某个固
定位置上,则该操作数或转移目标可用相对寻址方式。采用相对寻址方式时,指令中的地址
码字段 A给出一个偏移量,基准地址隐含由PC给出。即操作数有效地址或转移目标地址
EA=(PC)+A。这里的偏移量 A 是形式地址,有效地址或目标地址可以在当前指令之前
或之后,因而偏移量 A是一个带符号整数。相对寻址方式可用于实现共享代码的浮动或实
现程序的跳转执行。
8.基址寻址
基址寻址方式下,指令中的地址码字段 A给出一个偏移量,基准地址可以明显或隐含
地由基址寄存器B给出。操作数有效地址 EA=(B)+A。与变址方式一样,若任意一个通
用寄存器都可用作基址寄存器,则指令中必须明确给出通用寄存器编号R,并标明用作基址
第4章
95


<!-- page: 113 -->

计算机组成与系统结构(第3版)
96
寄存器。
基址寻址过程如图4.3所示,其中,基址寄存器R可以指定为任何一个通用寄存器。寄
存器 R的内容是基准地址,加上形式地址 A,形成操作数有效地址。
OP
R
A
寄存器堆
存储器
A
操作数
图4.3 基址寻址过程
变址、基址和相对3种寻址方式非常类似,都是将某个寄存器的内容与一个形式地址相
加来生成操作数的有效地址。通常把它们统称为偏移寻址。有些指令系统还将变址和基址
两种方式结合起来,形成基址加变址的寻址方式。
9.其他寻址方式
为缩短指令字长度,有些指令采用隐含地址码方式。即在指令中不明显给出操作数地
址或变址寄存器和基址寄存器编号,而是由操作码隐含指出。例如,单地址指令中只给出一
个操作数地址,另一个操作数隐含规定为累加器中的内容;此外,还有栈操作指令,其操作数
隐含为栈顶元素,指令中无须明显指出操作数地址。
4.2.4操作类型
指令系统的完备性要求在设计指令系统时必须考虑应提供哪些操作类型。通常操作类
型分为以下几种。
1.算术和逻辑运算指令
算术和逻辑运算指令有加(add)、减(sub)、比较(cmp)、乘(mul)、除(div)、与(and)、或
(or)、取反(not)、取负(neg)、异或(xor)、加1(inc)、减1(dec)等。
2.移位指令
移位指令有算术移位、逻辑移位、循环移位、半字交换等。有的指令系统中,一条移位指
令可以移动多位,此时通常用一个桶形移位器实现移位指令。
3.传送指令
传送指令通常有寄存器之间的传送(mov)、从内存单元读取数据到通用寄存器(load)、
从通用寄存器写数据到内存单元(store)等。
4. 串指令
串指令是对字符串进行操作的指令。如串传送、串比较、检索和传送转换等指令。
5.顺序控制指令
顺序控制指令用来控制程序执行的顺序。有条件转移(branch)、无条件转移(jmp)、跳
步(skip)、调用(call)、返回(ret)等指令。


<!-- page: 114 -->

指令系统
顺序控制类指令的功能通过将转移目标地址送到 PC中来实现。转移目标地址可用直
接寻址方式给出(又称绝对转移),或由相对寻址方式给出(又称相对转移)。有的机器还可
以用寄存器直接或寄存器间接寻址方式给出转移目标地址。
无条件转移指令在任何情况下都执行跳转执行,而条件转移指令(或称分支指令)仅在
特定条件满足时才跳转执行。转移条件一般是某个标志位的值,或者由两个或两个以上的
标志位组合而成,例如,CF=1、CF=0、CF=1或ZF=1等。这里CF为进位/借位标志,ZF
为零标志。
调用指令也称转子指令,和转移指令的根本区别在于执行调用指令时必须保存下条指
令的地址(称为返回地址)。调用指令用于子程序调用(即过程调用或函数调用),当子程序
(被调用过程)执行结束时,根据返回地址返回到主程序(调用过程)继续执行;而转移指令则
不返回执行,因而无须保存返回地址。
返回指令的功能是在子程序执行完毕时,将事先保存的返回地址送到PC,这样处理器
就能回到原来的主程序继续执行。
6.CPU 控制指令
CPU 控制指令有停机、开中断、关中断、系统模式切换以及进入特殊处理程序等指令。
大多数机器将这类指令划为“特权”指令(也称为管态指令),只能在内核代码执行时使用,以
防止因用户使用不当而对系统运行造成危害。
7.输入输出指令
输入输出指令用于完成 CPU与外部设备交换数据或传送控制命令及状态信息。大多
数机器都设置了这类指令,但是它们的寻址方式一般较少,常见的只有寄存器寻址、直接寻
址和寄存器间接寻址等。当外设中的I/O地址空间和主存地址空间统一编址时,可以不设
置这类指令,而用访存指令完成I/O操作。
4.2.5操作码编码
指令的操作码字段可以是固定长度,也可以是可变长度。选择定长操作码还是可变长
操作码,是时间和空间之间的开销权衡问题。希望降低空间开销时,缩短代码长度更重要,
应采用紧凑的变长操作码和变长指令字;希望降低时间开销以取得更好性能时,应采用定长
操作码和定长指令字。
1.定长操作码编码
定长操作码编码方式的操作码长度固定,译码方便,指令执行速度快,但有信息冗余。
例如,IBM360/370采用8位定长操作码,最多可有256条指令,但指令系统中只提供了
183条指令,有73种为冗余编码。如图4.4所示,其指令格式有RR型、RX型、RS型、SI
型、SS型等。操作码 OP中前两位用于指定4种不同指令格式:00为RR型,01为RX型,
10为 RS和 SI型,11为SS型。
其中,RR型的两个操作数和结果都在寄存器中;RX型和RS型都是寄存器-存储器型,
RX型是二地址指令,第一个操作数和结果放在R1中,另一个操作数在存储器中,采用基址
加变址寻址,有效地址EA=(X)+(B)+D;RS型是三地址指令,R1存放结果,R3存放一
个源操作数,另一源操作数的有效地址 EA=(B)+D;SI型是存储器-立即数型,结果和其中
一个操作数的地址共用同一个存储单元;SS型是存储器-存储器型指令,即两个操作数都是
第4章
97


<!-- page: 115 -->

计算机组成与系统结构(第3版)
98
RR型
RX型
RS型
SI型
OP
R1 R2
OP
RI X B
D
OP
R1 R3 B
D
OP
1
B
D
Ri:寄存器
X:变址器
Bi:基址器
Di:偏移量
1:立即数
L:数的长度
SS型
OP
L
B1
D1
B2
D2
8
8
第1个半字
4
12
第2个半字
4
12
第3个半字
图4.4 IBM360/370指令格式
存储器中的内容,用于字符串处理,L为字符串长度。
2.扩展操作码编码
扩展操作码编码方式将操作码的编码长度分成几种固定长度的格式。可以采用等长扩
展法,例如,按4-8-12、3-6-9这种等步长方式扩展,也可采用不等长扩展法。扩展编码方式
的操作码长度不固定,是可变的。这种编码方式被大多数非规整型指令集采用。
下面用一个例子来说明如何进行扩展操作码编码。
例4.1 设某指令系统的指令字为16位,每个地址码为6位。若二地址指令15条,单
地址指令34条,则剩下的零地址指令最多有多少条?
解:扩展编码的基本思想就是操作码按短到长进行扩展编码。二地址指令操作码最
短,零地址指令的操作码最长,所以,按照二地址→单地址→零地址的顺序进行编码。
二地址指令的地址码部分占12位,故操作码只有4位,最多有16种编码,用去15种编
码(0000~1110)分别表示15条指令,还剩一种编码1111未使用。
单地址指令的地址码部分占6位,故操作码有10位,最高4位为1111,还剩6位,最多
可有2?=64种编码,用其中的32+2=34种编码(11110 00000~11110 11111 和 11111 00000~
### 11111 00001)分别表示34条单地址指令。
剩下的零地址指令共有16 位操作码,编码范围为11111(00010~11111)(000000~
111111),即高5位固定为11111,次5位为00010~11111,低6位为000000~111111。因
此,零地址指令最多有30×2°种编码可用。
4.2.6标志信息的生成与使用
条件转移指令(也称分支指令)通常根据程序当前生成的标志信息进行转移。标志信息
也称为条件码(condition codes,CC)或状态位(status)。常用的标志有零标志ZF、溢出标志
OF、符号标志SF和进位/借位标志CF。对于不同数据类型的运算指令,这些标志信息的含
义有一些差别。
对于带符号整数加、减运算和无符号整数加、减运算,这4个标志的含义在3.3.1节中进
行了详细说明,并在图3.6(b)中给出了每个标志信息的生成电路。在执行定点整数加、减
运算指令和比较指令(通过做减法进行比较)时,CPU在ALU中进行相应的加或减运算,得
到运算结果以及相应的标志信息。


<!-- page: 116 -->

指令系统
对于逻辑运算指令,通常只有零标志ZF才有意义。可通过判断是否ZF=1来确定与、
或、非等操作的结果是否为0。对于移位指令,因为左移一位,数值扩大一倍,所以左移指令
的结果可能会发生溢出。因此,有些机器的左移指令会生成 OF标志。还有的机器在算术
左移时将操作数的最高位移入进位标志,通过判断符号标志和进位标志是否相等来判断是
否发生了溢出。
生成的标志位可由专门的条件码寄存器(或称状态寄存器、标志寄存器、程序状态字寄
存器①)来存放,也可由指定的通用寄存器来存放。有些机器不用专门的标志寄存器存放标
志位,而是用通用寄存器来保存。不同机器的说法和做法类似,但不一定完全相同。
表 4.1列出了IA-32 指令系统中部分条件转移指令的转移条件。
表 4.1 IA-32 中部分条件转移指令
序 号
指令
转 移 条 件
说 明
1
ja/inbe label
CF=0 AND ZF=0
无符号整数 A>B
2
jae/inb label
CF=0 OR ZF=1
无符号整数 A≥B
3
jb/jnae label
CF=1 ANDZF=0
无符号整数 A<B
4
jbe/jna label
CF=1 OR ZF=1
无符号整数 A≤B
5
jg/inle label
SF=OF AND ZF=0
带符号整数 A>B
6
ige/jnl label
SF=OF OR ZF=1
带符号整数 A≥B
7
jl/jnge label
SF≠OF AND ZF=0
带符号整数 A<B
8
jle/jng label
SF≠OF OR ZF=1
带符号整数 A≤B
IA-32中某些运算类指令执行后,CPU会根据运算结果产生相应的进/借位标志CF、符
号标志SF、溢出标志OF和零标志ZF等,并保存到标志寄存器(EFLAGS)中。对于比较大
小后进行分支转移的情况,通过减法来获得标志信息,然后再根据标志信息来判定两个数的
大小,从而决定转移到何处执行指令。
对于无符号整数,ZF=1说明两数相等,CF=1说明有借位,是“小于”的关系,通过对
ZF和CF的组合,得到表4.1中前4条指令中的结论;对于带符号整数,ZF=1说明两数相
等,SF=OF说明结果是以下两种情况之一:①两数之差为正数(SF=0)且结果未溢出
(OF=0);②两数之差为负数(SF=1)且结果溢出(OF=1),这两种情况显然反映的是“大
于”关系。若SF≠OF,则反映“小于”关系,因而带符号整数比较时对应表4.1中后面4条指
令中的条件。
4.2.7指令系统设计风格
1.按操作数位置指定风格来分
按操作数位置指定风格来分,可分为以下4种不同类型的指令系统。
① 程序状态字寄存器用来存放条件码CC和自陷允许标志(trap enable flag)等状态信息。不同计算机对程序状态
的描述以及程序状态存放位置可能不一样。但在概念上应该有一个程序状态字(program status word.PSW)。
第4章
99


<!-- page: 117 -->

计算机组成与系统结构(第3版)
100
1)累加器(accumulator)型指令系统
累加器型指令系统中,总是把其中一个操作数隐含在累加器中,结果也在累加器中。虽
然其指令字短,但每次运算都要通过累加器,因而,对于复杂表达式,编译器需生成许多移
入/移出累加器的指令,从而使程序变长,影响程序执行效率。这种设计风格的指令系统只
在早期机器中使用过,现在一般不采用。
2)栈(stack)型指令系统
Java 虚拟机采用的是栈型指令系统。栈是一种采用先进后出(FILO)存取方式的特定
存储区。栈型指令系统中,规定指令的操作数总是来自栈顶。往栈里存数称为入栈或压栈,
从栈里取数叫出栈或弹出。
栈型指令系统中的指令都是零地址或单地址指令,因此,指令字很短。但是,由于指令
所用操作数只能来自栈顶,所以,在对表达式进行编译时,所生成的指令顺序以及操作数在
栈中的排列都有严格的顺序规定,因而不灵活,带来指令条数的增加。因此,栈型指令系统
很少被通用计算机使用。
3)通用寄存器(general purpose register)型指令系统
通用寄存器型指令系统的特点是,使用通用寄存器而不是累加器来存放临时数据,其指
令操作数可以是立即数,或来自通用寄存器,或来自存储单元。
4)Load/Store型指令系统
Load/Store型指令系统也使用通用寄存器而不是累加器来存放临时数据。因此,它也
是一种通用寄存器型指令系统。同时,它有一个显著的特点,就是只有取数(load)指令和存
数(store)指令才可以访问存储器,运算类指令不能访存。Load/Store型指令系统中的指令
比较规整,体现在指令的长度和指令执行时间等能够比较一致。
2.按指令格式的复杂度来分
按指令格式的复杂度来分,可分为CISC与RISC两种类型指令系统。
1)CISC风格指令系统
随着 VLSI技术的迅速发展,计算机硬件成本不断下降,软件成本不断上升。为此,人
们在设计指令系统时增加了越来越多功能强大的复杂指令,以使指令功能接近高级语言语
句的功能,给软件提供较好的支持。例如,VAX-11/780指令系统包含了16种寻址方式,9
种数据格式,303条指令,而且一条指令包含1~2字节的操作码和下续 N个操作数说明
符,而一个操作数说明符的长度可达1~10字节。称这类计算机为复杂指令集计算机
(complex instruction set computer,CISC)。
复杂的指令系统使得计算机的结构变得复杂,不仅增加了研制周期和成本,而且难以保
证其正确性,甚至降低了系统性能。对大量典型的CISC程序进行了调查,结果表明,各种
指令的使用频率相当悬殊,最常使用的是只占指令系统20??一些简单指令,它们占程序
代码的80??上,而需要大量硬件支持的复杂指令在程序中的出现频率却很低,这造成了
硬件资源的大量浪费。因此,20世纪70年代中期,一些高校和公司开始研究指令系统的合
理性问题,提出了精简指令集计算机(reduced instruction set computer,RISC)的概念。
2)RISC 风格指令系统
RISC的着眼点不是简单地放在简化指令系统上,而是通过简化指令使计算机结构更
加简单合理,从而提高机器的性能。与CISC相比,RISC 指令系统的主要特点如下。


<!-- page: 118 -->

指令系统
(1)指令数目少。只包含使用频度高的简单指令。
(2)指令格式规整。寻址方式少、指令格式少、指令长度一致。
(3)采用Load/Store型指令设计风格。
(4)采用流水线方式执行指令。规整的指令格式有利于采用流水线方式执行。
(5)采用大量通用寄存器。编译器可将变量分配到通用寄存器中,以减少访存次数。
(6)采用硬连线控制器。指令少而规整使得控制器的实现变得简单,可以不用或少用
微程序控制。
(7)采用优化的编译系统。指令数少有利于编译器的优化。
采用 RISC技术后,由于指令系统简单,CPU的控制逻辑大大简化,芯片上可设置更多
的通用寄存器,指令也可以采用速度较快的硬连线控制器来控制,且更适合于采用指令流水
技术,这些都可以使指令的执行速度进一步提高。
虽然 RISC技术在性能上有优势,但最终 RISC机并没有在个人计算机和服务器市场上
占优势,反而Intel公司一直保持较大份额,其原因主要有两点:第一,因为软件的向后兼容
性,许多用户先期花了很多钱投资购买了在Intel系列机上开发的软件,如果换成 RISC机,
就意味着所有软件要重新投资;其次,随着处理器速度和芯片密度等的不断提高,RISC系
统也日趋复杂,而CISC由于采用了部分RISC技术(如Intel 微架构中将简单指令直接转换
为类 RISC指令,复杂指令用微码实现),使其性能更加提高。虽然这种混合方案不如纯
RISC方案速度快,但它却能在保证软件兼容的前提下达到具有较强竞争力的整体性能。
不过,随着后个人计算机时代的到来,个人移动设备的使用和嵌入式系统的应用越来越
广泛,像 ARM处理器等这些采用RICS技术的产品又迎来了新的机遇,在嵌入式系统中占
有绝对优势,因而被更广泛使用。
4.2.8异常和中断处理机制
异常和中断并不是指令,但异常和中断处理机制是指令系统必须考虑的重要内容。在
程序正常执行过程中,某些指令的执行会遇到一些异常或特殊情况而无法继续,这种中断
CPU中程序正常执行的情况主要有“异常”和“中断”两大类。
在早期的Intel8086/8088系统中,并不区分异常和中断,两者统称为中断,由CPU内
部产生的意外事件称为“内中断”;从 CPU外部通过中断请求引脚INTR和NMI向 CPU
发出的中断请求为“外中断”。
从Intel80286开始,Intel公司统一把“内中断”称为异常,而把“外中断”称为中断。在
IA-32架构说明文档中,Intel公司对异常和中断进行了如下描述:处理器提供了异常和中
断这两种打断程序正常执行的机制。中断是一种典型的由I/O设备触发的、与当前正在执
行的指令无关的异步事件;而异常是处理器执行一条指令时,由处理器在其内部检测到的、
与正在执行的指令相关的同步事件。
实际上,异常和中断两者的处理过程基本上是相同的,这也是在有些系统架构或教科书
中将两者统称为“中断”或统称为“异常”的原因。
1.异常
异常(exception)也称为例外,是指处理器在执行某条指令时发生在CPU 内部的事件。
如整除 0、溢出、断点设置、单步跟踪、访问超时、非法操作码、栈溢出、缺页、保护错等。内部
第4章
101


<!-- page: 119 -->

计算机组成与系统结构(第3版)
102
异常分为故障(fault)、自陷(trap)和终止(abort)三类。
1)故障
故障也称为失效,它是引起故障的指令在执行过程中被检测到的一类异常事件。例如,
指令译码时,遇到“非法操作码”;取指令或数据时,发生“缺页”或“保护错”;执行整数除法指
令时,发现“除数为0”等。显然,“缺页”这类异常处理后,操作系统已将需要的页从外存调
到主存,因此可继续返回到发生故障的指令继续执行;对于“非法操作码”“保护错”“整数除
0”等异常,因为无法通过异常处理程序恢复故障,因此不能回到原断点继续执行,必须终止
进程的执行。有关“缺页”和“保护错”等存储器访问异常的概念参见第7章相关内容。
2)自陷
自陷也称为陷阱或陷入,与故障等其他异常事件不同,它是预先安排的一种“异常”事
件,就像预先设定的“陷阱”一样。通常的做法是,事先在程序中用一条特殊指令或通过某种
方式设定特殊控制标志来人为设置一个“陷阱”,当执行到满足条件的自陷指令时,CPU自
动根据不同“陷阱”类型进行相应的处理,自陷异常处理结束后,将返回到自陷指令的下条指
令执行。
通常,用于程序调试的“单步跟踪”和“断点设置”功能都通过“自陷”方式来实现。此外,
还有系统调用指令、条件自陷指令等都属于自陷指令。执行到这些指令时,将无条件或有条
件地自动调出操作系统内核程序或陷入特定的异常处理程序进行处理。
3)终止
如果在执行指令过程中发生了严重错误,例如,访问指令或数据时,DRAM或 SRAM
发生校验错,则程序将无法继续执行,只能终止发生问题的进程,在有些严重的情况下,甚至
要重启系统。
2.中断
程序执行过程中,若外设完成任务或发生某些特殊事件(如打印机缺纸、定时采样计数
时间到、键盘缓冲满等),会向CPU发中断(interrupt)请求,要求 CPU对这些情况进行处
理。通常,每条指令执行完后,CPU都会主动去查询有没有中断请求,有的话,则将下条指
令地址作为返回地址(断点)保存,然后转到相应的中断服务程序执行,结束后回到断点继续
执行。
中断事件与执行的指令无关,由CPU外部的I/O部件发出,因此,称为I/O中断或外
部中断,需要通过专门的中断请求线向CPU 请求。
指令集架构(ISA)必须对以上所述的异常和中断类型的定义、自陷指令、中断允许位、
异常/中断原因的识别和记录、断点信息的保存、异常/中断整个处理过程中软硬件之间的协
同等各个方面给出相应的规定。
4.3程序的机器级表示
不管用什么高级语言编写的源程序最终都必须翻译(汇编、解释或编译)成以指令形式
表示的机器语言,才能在计算机上运行。本节简单介绍高级语言源程序转换为机器代码过
程中涉及的一些基本问题。为方便起见,本节选择具体语言进行说明,高级语言和机器语言
分别选用C语言和 MIPS指令系统。其他情况下,其基本原理不变。