计算机组成原理 第四章
第四章 指令系统
指令系统的发展和性能要求
指令的概念
计算机的程序是由一系列有序且有一定意义的指令组成的指令
:命令计算机执行某种基本操作的二进制代码串
- 每条指令可以完成一个独立的算术运算或逻辑运算操作,或者数据传送等基本操作
- 直接由硬件支持、软件可控制的最小的动作单位
程序员按照指令格式编写软件而不必考虑机器如何实现指令的功能(即,软硬件的设计是透明的)
指令系统(Instruction Set)
:一台计算机能直接理解与执行的全部指令的集合
决定计算机的基本功能,软件与硬件的界面
计算机系统设计的一个核心问题
指令系统是软件和硬件之间的接口
指令:
微指令
:微程序级的命令,属于硬件,软件不可见宏指令
:由若干条机器指令组成的软件指令,属于软件,硬件不可见机器指令
:介于微指令与宏指令之间,简称指令,每条指令可完成一个独立的算术运算或逻辑运算(软硬件可见)
指令系统的发展过程
- 50年代,指令系统只有定点加减、逻辑运算、数据传送、转移等十几至几十条指令
- 60年代后期,增加了乘除、浮点、十进制、字符串处理等指令,指令数目多达一二百条,寻址方式也趋多样化,开始出现系列计算机
- 70年代末期,大多数计算机的指令系统多达几百条,称这些计算机为复杂指令系统计算机(
CISC
Complex Instruction SetComputer)
庞大的指令系统难以保证正确性,不易调试维护,造成硬件资源浪费,精简指令系统计算机(RISC
Reduced Instruction Set Computer)出现,可靠性高,速度快
指令系统的性能要求
低级语言与硬件结构的关系
高级语言(算法语言)
:语法与具体机器的指令系统基本无关,编程难度低,可维护性高
低级语言
:面向机器,和具体机器的指令系统密切相关,时空效率高
- 低级语言分为机器语言(二进制语言)和汇编语言(符号语言)
- 低级语言都是面向机器的语言,和具体机器的指令系统密切相关
高级语言与低级语言的性能比较
指令格式
指令字(指令)
:表示一条指令的机器字指令格式
:指令字用二进制代码表示的结构形式
机器执行一条指令所必须的全部信息都必须 明显或隐含地在指令中给出
操作码字段OC
:表征指令的操作特性与功能地址码字段AC
:指定参与操作的操作数的地址
计算机指令可以根据不同的分类方式进行归类。以下是几种常见的分类方式和对应的指令种类:
操作类型分类:计算机指令可以分为数据传输指令、算术逻辑指令、转移指令、程序控制指令等。
寻址方式分类:计算机指令可以分为立即数寻址、直接寻址、间接寻址、相对寻址等。
指令长度分类:计算机指令可以分为定长指令和变长指令。
功能分类:计算机指令可以分为系统指令、用户指令等。
指令执行方式分类:计算机指令可以分为单操作数指令、双操作数指令等。
以上仅仅是对于计算机指令的简单分类,具体的指令种类会因为各种架构而有所不同,同时不同的指令集还会在指令的数量、精度等方面存在差异。
操作码
- 每一条指令都有一个操作码,表示该指令应进行什么性质的操作
- 不同的指令用操作码字段的不同编码表示
- 操作码字段的位数一般取决于计算机指令系统的规模
- 一个特定的机器的指令系统,不同指令字中操作码字段和地址码字段的长度可以相同,也可以不同
等长操作码
:
- 固定长度,所占的二进制位数固定不变
- 如果系统中所有指令的操作码都用n位二进制数表示,则系统中的指令条数不会超过$2^n$条
- 有利于简化硬件设计,减少指令译码时间
- 广泛用于字长较长的计算机的指令系统中
可变长度操作码
:
- 不同的指令的操作码长度不同
- 操作码扩展技术(使得平均操作码长度更短):
- 地址数少的指令使用较长的操作码,地址数多的指令使用较短的操作码
- 使用频度高的指令分配短的操作码,使用频度低的指令分配较长的操作码
- 优点:
- 有效缩短操作码的平均长度,节省存储空间
- 缩短常用指令的译码时间,提高程序的运行速度
- 缺点:指令译码系统比等长操作码复杂,需要判断操作码字段
- 在字长较短的微型机中应用广泛
地址码
指令中的地址码用来指出该指令的源操作数地址(0至2个)、目标操作数(结果)地址,以及下一条指令的地址
操作数的存放位置:
主存单元
CPU内部数据寄存器
I/O设备接口内的寄存器
如果一条指令中有n个操作数地址,则将该指令称为n操作数指令或n地址指令
地址码字段的基本信息
- 操作数或操作数的地址
- 存放运算结果的地址:
寄存器编号
主存地址
I/O地址
不同操作数的指令:
三地址指令
二地址指令
一地址指令
零地址指令
四地址指令
OP:操作码
$A_1$:第一地址码,存放被操作数(第一源操作数)
$A_2$:第二地址码,存放操作数(第二源操作数)
$A_3$:第三地址码,存放操作结果
$A_4$:第四地址码,存放下条要执行指令的地址
操作:$(A_1)OP(A_2)→A_3$,从$A_4$取下一条
指令可直接寻址的地址范围与地址字段的位数有关
- 例:指令字长32位,操作码占8位,4个地址段各占6位,则指令的直接寻址范围为:$2^6 = 64$
如果地址字段均指示主存的地址,则一条四地址指令执行时共需访存四次
优点:指令直观易懂,后续指令的地址可任意安排
缺点:指令长度长
地址的个数
非转移类指令的下一条指令地址:
用于算术运算、逻辑运算、数据传输
首地址+指令长度
转移类指令:
用于改变程序的执行顺序,包括跳转指令、条件跳转指令和调用指令等
通常不需要源操作数地址和结果地址
三地址指令
A1: 被操作数(第一源操作数)地址
A2 :操作数(第二源操作数)地址
A3 :存放结果的地址
非转移类指令:顺序执行后续指令
功能: $(A_1) OP (A_2) → A_3$
注意:第二源操作数是用于计算结果的输入操作数;而目的操作数是用于存储结果的输出操作数
二地址指令
双操作数操作:
$(A_1) OP (A_2) → A_1$
A1:既作被操作数(第一源操作数)地址,又作目的操作数地址
A2:操作数(第二源操作数)地址
$(A_1) OP (A_2) → A_2$
A1:被操作数(源操作数)地址
A2:操作数(目的操作数)地址
一地址指令(单操作数指令)
双操作数操作:(A) OP (X) → X
A:第一源操作数地址
X:第二源操作数地址和目的操作数地址,隐含使用寄存器或堆栈寻址
单操作数操作:OP (A) → A
A:既作被操作数地址,又作目的操作数地址
零地址指令
指令字中只有操作码,没有地址码
无需操作数的指令,如空操作(NOP,占用一段时间或空间)、停机等
运算的操作数地址全部隐含
源操作数和结果隐含使用寄存器、堆栈或特定操作数
双操作数运算指令的三种类型
存储器-存储器(SS)型指令
- 参与运算的操作数都放在内存中
- 机器执行SS型指令需多次访问内存
- 执行时间最长
寄存器-寄存器(RR)型指令
- 参与运算的操作数都放CPU内部的数据寄存器中
- 机器执行RR型指令速度快,但需要多个寄存器
- 执行速度快
寄存器-存储器(RS)型指令
- 执行RS型指令时,既要访存,又要访问寄存器
- 执行速度在SS和RR之间
定长操作码举例
例:某指令字长16位,具有三地址、二地址、一地址和零地址4类指令,每个地址占4位,采用定长操作码方案,最多可表示多少条指令?
答:24\=16条
扩展操作码举例
例:某指令字长16位,具有三地址、二地址、一地址和零地址4类指令,每个地址占4位,要求有15条三地址指令、15条二地址指令、15条一地址指令和16条零地址指令,指令格式如何设计?
例:设某指令系统字长为16位,地址码为4位。试设计指令格式,使该系统中有11条三地址指令、70条二地址指令和150条单地址指令。并指明该系统中最多还可以有多少条零地址指令
注意:1,不允许短码是长码的前缀
2,各条指令的操作码一定不能重复
例题:
指令字长与机器字长
机器字长
(简称字长):计算机能直接处理的二进制数据的位数,它决定了计算机的运算精度,通常是CPU运算器的字长
- 字长越长,计算机的运算精度越高
- 为便于处理字符数据及尽可能地利用存储空间,一般把机器字长定为字节长度的整数倍
指令字长
:一个指令字中二进制代码的位数
- 取决于操作码的长度、操作数地址的长度和操作数地址的个数
- 通常指令字长等于机器字长的整数倍
- 如果机器字较长,指令字长也可是机器字长的一半的整数倍
指令字长与机器字长的关系
单字长指令:指令字长等于机器字长
半字长指令:指令字长等于半个机器字长
双字长指令:指令字长等于两个机器字长
多字长指令:优点
:可以给操作码和地址码提供较大的空间缺点
:可以给操作码和地址码提供较大的空间
指令字结构
等长指令字结构
:一个指令系统中各种指令字长度是相等的
特点:结构简单,控制方便,实现复杂度低
变长指令字结构
:一个指令系统中,指令字的长度随指令功能而变化
特点:结构灵活,能充分利用指令长度,但指令的译码及控制较复杂
指令助记符
为了便于书写和阅读程序,每条指令通常用3个或4个英文缩写字母来表示。这种缩写字符叫做指令助记符
不同的指令系统中,同样或类似的操作所采用的助记符并不相同
指令和数据的寻址方式
指令的寻址方式
寻址方式:形成指令或操作数的内存地址的方式
指令寻址方式:用于形成指令在内存中的地址
数据寻址方式:用于形成操作数在内存中的地址
顺序寻址方式:
通常情况下,指令在内存中是按顺序存放的:指令的执行顺序就是指令在内存中的存放顺序
程序顺序执行过程:
- CPU从存储器地址A1取出第一条指令,然后执行这条指令
- 接着从存储器地址A1后面相邻地址取出第二条指令,并执行第二条指令
- 接着再取出第三条指令
- 依此类推……
程序计数器(指令指针寄存器)PC
:自动加上指令长度,形成下一次的取指地址
跳跃(转移)寻址方式
下条指令的地址码不是顺序地由程序计数器PC给出,而是由本条指令给出
转移指令的地址码字段包含下一条指令地址的信息
执行跳跃指令时,将通过指令获得的地址码送入PC中
采用跳跃寻址方式,可以实现程序转移或构成循环程序
操作数寻址方式
操作数的三个来源:
- 由指令中的地址码部分直接给出操作数
- 操作数存放在CPU内的数据寄存器中
- 操作数存放在内存的数据区(含I/O寄存器)中
- 在指令中直接给出操作数的内存有效地址
- 指令的地址字段给出形式地址(位移量),在指令执行时,形式地址依据某种方式变换为有 效地址再存取操作数
有些指令固定使用某种寻址方式
有些指令允许使用多种寻址方式:
- 在指令中加入寻址方式字段指明
- 对不同的寻址方式分配不同的操作码(看作不同指令)
操作数寻址方式的类型
- 立即寻址
- 寄存器寻址
- 直接寻址
- 间接寻址
- 寄存器间接寻址
- 隐含寻址
- 偏移寻址
- 段寻址
- 堆栈寻址
立即寻址
指令的地址字段指出的不是操作数的地址,而是操作数本身
例:指令 MOV AX,100H
100H
就是立即数
特点
:
指令中直接给出了操作数,不需要通过访问内存来取数,因而指令执行时间很短
操作数的范围有限
灵活性差
寄存器寻址
操作数不放在内存中,而是放在CPU内部的通用寄存器中
指令中给出的操作数地址不是内存的地址单元号,而是通用寄存器的编号
例如,指令: ADD R0,R1
(R0)+(R1)→R0 (操作数在寄存器中)
特点
:指令通常比较短,指令执行时间短
直接寻址
在指令格式的地址字段中,直接给出操作数在内存的地址A
指令字中的形式地址A,就是操作数的有效地址EA
,通常把形式地址A又称为直接地址
用D表示操作数,那么直接寻址的表达式为:D=(A)
例如: MOV AX,[3000H]
间接寻址
形式地址A既不是操作数D,也不是操作数D的真正地址,而是操作数地址的指示器,即:A的内容才是操作数的有效地址
间接寻址示意图
直接寻址和间接寻址结合起来,有如下形式:
寻址特征位 I
I=0,直接寻址,有效地址:EA=A
I=1,间接寻址,有效地址:EA=(A)
在计算机的指令系统中,变址X和间址I是用于寻址内存位置的两个概念。它们通常与基址B和外设寄存器R一起使用。
变址X是指用于计算内存地址偏移量的值,通常是在执行指令时从寄存器或内存位置读取的一个值。当计算机需要访问某个内存位置时,会将变址X添加到基址B(如果有)上,得到最终的内存地址。
间址I是指直接指定的内存地址,通常是在指令本身中给定的一个值。当计算机需要访问间址I所指向的内存位置时,会忽略基址B和变址X。
在某些指令集中,寻址特征位是用来指示该指令是否使用了变址X或间址I的标志位。例如,在x86指令集中,可以使用如下方式来表示不同的寻址模式:
直接寻址:mov eax, [0x12345678]
基址加偏移量寻址:mov eax, [ebx + 0x10]
变址寻址:mov eax, [eax + edx 4]
基址加变址寻址:mov eax, [ebx + eax 2]
其中,第一种情况使用了间址I;第二种情况使用了基址B和固定的偏移量;第三种情况使用了变址X和一个固定的缩放因子;第四种情况同时使用了基址B和变址X。这些寻址特征位可以在指令编码中进行标记,以便计算机能够正确地解析指令并访问相应的内存位置。
寄存器间接寻址
指令中指定的寄存器中的内容不是操作数,而是操作数的地址,即:EA =(R)指明的操作数是在内存中!
示意图:
隐含寻址
在指令中不明显地给出操作数的地址
指令中的某个操作数或其地址隐含在某个通用寄存器或指定的内存单元中
例:DIV BL
AX / BL,商存AL中,余数存AH中
偏移寻址
直接寻址和寄存器间接寻址的结合
有效地址:EA=A+(R)
要求指令中有两个地址字段,至少其中一个是显式的
三种类型:
相对寻址
基址寻址
变址寻址
相对寻址
把程序计数器PC的内容加上指令中给出的形式地址A,进而形成操作数的有效地址
形式地址A称为位移量,其值可正可负,相对于当前指 令地址进行浮动
便于程序在内存中成块搬动
即: EA =(PC)+A
优点
:指令中不必给出绝对地址,指令长度可以缩短,程序可以放在内存任何位置
基址寻址
将CPU中基址寄存器RB的内容加上指令中给定的形式地址A,而形成操作数的有效地址
基址寄存器的位数可以大于形式地址A的位数,从而可以扩大操作数的寻址范围
即:E=(RB)+A
变址寻址
把CPU中某个变址寄存器RX的内容与偏移量A相加,形成操作数有效地址
即:EA=(RX)+A
基址寻址和变址寻址的区别:
- 基址寻址的目的:扩大寻址空间和实现多道程序
- 变址寻址的目的:访问复合数据结构
- 变址寄存器在每次使用后其值可以自动或用指令修改;基址寄存器通常是不变的
段寻址方式
程序中的指令和数据按照逻辑结构首先分成段, 每个段内均以段起始地址为基址编址
微型机中采用了段寻址方式,其实质还是基址寻址基地址就是CPU中的段寄存器
特例:
如何在16位机中形成20位的地址,从而获得1MB存储空间的直接寻址能力?
将整个1MB空间存储器按照最大长度64KB为单位划分成若干段。在寻址一个具体的内存单元时,由一个基地址(段寄存器)再加上寄存器提供的16位偏移量来形成实际的20位物理地址。
约定段的起始地址末四位必须为0000,故用16位段寄存器指明20位段基址
在形成20位物理地址时,段寄存器中的16位数会自动左移4位,然后与16位偏移量相加,即可形成所需的20位的内存地址
堆栈寻址
对堆栈的操作:
向堆栈中增加数据(数据入栈,进栈)
从堆栈中取走数据(数据出栈,退栈)
CPU执行入栈和出栈操作时并不直接给出被操作的单元的地址,而是依据数据入出栈的顺序由硬件或软件自动给出地址,或是自动保证按顺序对数据进行操作
存储原则:先进后出
堆栈有两种形式:寄存器堆栈
和存储器堆栈
存储器堆栈(软堆栈)
利用常规内存空间的某一部分或某几部分实现存储器堆栈
每个软堆栈有一个固定的栈底和一个浮动的栈顶
CPU内部设置一个堆栈指针(堆栈指示器)SP指示当前栈顶的位置
堆栈指示器指定的存储器单元就是堆栈的栈顶
栈底的位置固定,无需存储
存储器堆栈入栈(进栈)操作
push A:
(A)→M[SP]
(SP)-1→SP
(A):通用寄存器/内存单元A的内容
SP:堆栈指示器
M[SP]:堆栈指针指示的存储器栈顶单元
存储器堆栈出栈(退栈)操作
pop A:
(SP)+1→SP
M[SP]→ A
(A):通用寄存器/内存单元A的内容
SP:堆栈指示器
M[SP]:堆栈指针指示的存储器栈顶单元
栈顶指针的位置:
实现方式一:总是指向下一个入栈位置(无内容的栈顶)
实现方式二:总是指向下一个出栈位置(有内容的栈顶)
两种实现方式入栈和出栈操作和修改堆栈指针的操作的 顺序相反
堆栈指针的+1和-1操作:以一个存储字的长度为 单位修改堆栈指针(+Δ;-Δ)
软堆栈的两种生长方式
栈顶地址比栈底地址小:向下生长的堆栈
栈顶地址比栈底地址大:向上生长的堆栈
Pentium寻址方式
典型指令
一个较完善的指令系统,应当有数据处理
、数据存储
、数据传送
、程序控制
四大类。
指令类型:
数据传送指令
算术运算指令
逻辑运算指令
移位操作指令
程序控制指令
输入输出指令
串处理指令
特权指令
数据传送类指令
功能:
实现寄存器与寄存器、寄存器与存储单元以及存储单元与存储单元之间的数据传送
类型:
一般传送指令
取数(load)、存数(store)、传送(mov)、成组传送 |
堆栈操作指令
入栈、出栈 |
数据交换指令
字节交换、字交换 |
算术运算指令
功能:定点数或浮点数的算术运算
依据机器硬件功能的不同,算术运算指令的多少各不相同:
简单的CPU无乘除法指令
高档的CPU支持浮点运算
并行机有向量运算指令
类型:二进制定点加、减、乘、除指令
浮点加、减、乘、除指令
十进制加、减运算指令
逻辑运算指令
功能:
与、或、非、异或等逻辑运算功能以及一些位操作
主要用于无符号数的位操作、代码的转换、判断及运算
各个比特之间无进位、借位关系
类型:
与、或、非、异或、位测试、位置位、位清除、位取反 |
移位操作指令
功能:
对寄存器或内存单元的内容实现左移、右移或循环移位
含算术移位(符号不移位)和逻辑移位(所有位均移位)指令
类型:左移、右移、算术移位、逻辑移位、循环移位、单向移位
程序控制类指令
功能:
控制程序的执行顺序,对PC进行操作
无条件转移、条件转移(进位、零、负、 溢出) |
循环指令 |
子程序调用及返回指令、返回主程序指令 |
中断调用与中断返回指令(程序随机切换,无法预期) |
输入输出类指令
功能:
在I/O独立编址方式中,输入输出指令实现CPU内的寄存器与外部设备接口之间的信息交换
- 例如:启动外围设备,检查测试外围设备的工作状态等
在I/O与存储器统一编址方式中,由访存指令实现CPU内的寄存器与外部设备接口之间的信息交换
统一编址的机器指令系统中没有输入输出类指令
类型:输入指令、输出指令
串处理指令
功能:
对成批的数据进行处理
类型:字符串传送、字符串转换、字符串比较、字符串查找、字符串抽取、字符串替换
特权指令
功能:
具有特殊权限的指令,只用于操作系统或其他系统软件
在多用户、多任务的计算机系统中用于系统资源的分配和管理
类型:存储管理指令、停机指令、系统状态控制指令
其他指令
类型:状态寄存器置位、复位指令
暂停指令
空操作指令
自陷(TRAP)指令
系统控制用的特殊指令
计算机指令系统的分类
CISC
复杂指令系统RISC
精简指令系统
CISC的主要特点
- 指令系统复杂,指令数量多、寻址方式多、指令格式多
- 绝大多数指令需要多个CPU周期才能执行完成
- 各种指令都可访问存储器
- 采用微程序控制
- 有专用寄存器
- 难以用优化编译生成高效的目标代码程序
CISC举例
CISC(复杂指令集计算机)的指令系统一般多达二三百条指令
VAX11/780计算机有303条指令,18种寻址方式
Pentium机也有191条指令,9种寻址方式
RISC的主要特点
- 简化的指令系统,指令数量少、寻址方式少、指令格式少、指令长度固定,选取使用频率最高的一些简单指令,去掉使用频率低而又可以通过高频率简单指令组合实现其功能的指令
- 尽量使用R-R操作指令,只有取数load/存数store指令访问存储器
- 使用较多的通用寄存器以减少访存
- 一般采用硬布线控制方式,不采用或少采用微程序控制方式
- 采用多级指令流水线结构,处理机在同一时间内可执行多条指令,可在一个机器周期内执行完毕
- 采用优化编译技术,保证流水线畅通,对寄存器分配进行优化
RISC和CISC的比较
设
高级语言程序经编译后在机器上运行的机器指令数为I
每条机器指令执行时所需要的平均机器周期数是C
每个机器周期的执行时间为T
计算机执行程序的时间P计算:P=I×C×T
RISC处理机实例:SPARC
在SPARC中,有一些指令没有选入指令系统,但很容易使用指令系统中的另外一条指令来替代实现。下表左半部列出 了6条指令的功能。请在表的右半部填入替代指令及实现方法。
约定:当某些指令中地址字段为寄存器R0的编号时,以立即数0(而不是R0的内容)作为操作数
ARMv8-A架构支持的指令集
两种执行状态(Execution State):
- AArch64执行状态
- A64指令集则使用64位工作寄存器
- 使用64位计算模式
- 所有指令均为32位等长指令字(4字节)
- AArch32执行状态
- A32指令集:
- 对应ARMv7架构及其之前的ARM指令集
- 32位等长指令字
- T32指令集
- 对应ARMv7架构及其之前的Thumb/Thumb-2指 令集
- 16位和32位可变长指令字结构
- A32指令集:
- 均支持SIMD(Single Instruction Multiple Data)和浮点运算指令