一、指令系统
1. 指令集体系结构
指令(机器指令)是指示计算机执行某种操作的命令,是计算机运行的最小功能单位。一台计算机的所有指令的集合构成该机的指令系统,也称指令集。
指令系统是指令集体系结构(ISA)中最核心的部分, ISA 完整定义了软件和硬件之间的接口(指令集体系结构处于软硬件的交界面上),是机器语言或汇编语言程序员所应熟悉的。ISA 规定的内容主要包括:指令格式,数据类型及格式,操作数的存放方式,程序可访问的寄存器个数、位数和编号,存储空间的大小和编址方式,寻址方式,指令执行过程的控制方式等。
注:一台计算机只能执行自己指令系统中的指令,不能执行其他系统的指令。
2. 指令的基本格式和分类
【总结】:
1)指令的构成
-
操作码指出指令中该指令应该执行什么性质的操作以及具有何种功能。操作码是识别指令、了解指令功能及区分操作数地址内容的组成和使用方法等的关键信息。
例如,指出是算术加运算还是算术减运算,是程序转移还是返回操作。 -
地址码给出被操作的信息(指令或数据)的地址,包括参加运算的一个或多个操作数所在的地址、运算结果的保存地址、程序的转移地址、被调用的子程序的入口地址等。
2)按地址码数目分类
根据指令中操作数地址码的数目的不同,可将指令分成:零地址指令、一地址指令、二地址指令、三地址指令和四地址指令。
① 零地址指令:
只给出操作码 OP ,没有显式地址。这种指令有两种可能:
注意:堆栈指令的访存次数,取决于采用的是软堆栈还是硬堆栈。若是软堆栈(堆栈区由内存实现),则对于双目运算需要访问 4 次内存:取指、取源数1 、取源数2 、存结果。若是硬堆栈(堆栈区由寄存器实现), 则只需在取指令时访问一次内存。
② 一地址指令:
这种指令也有两种常见的形态,要根据操作码的含义确定究竟是哪一种。
③ 二地址指令:
对于常用的算术和逻辑运算指令,往往要求使用两个操作数,需分别给出目的操作数和源操作数的地址,其中目的操作数地址还用于保存本次的运算结果。
④ 三地址指令:
⑤ 四地址指令:
3)按指令长度分类
指令的长度是指一条指令中所包含的二进制代码的位数。指令字长取决于操作码的长度、操作数地址码的长度和操作数地址的个数。
指令长度与机器字长没有固定的关系,它可以等于机器字长,也可以大于或小于机器字长。通常,把指令长度等于机器字长的指令称为单字长指令,指令长度等于半个机器字长的指令称为半字长指令,指令长度等于两个机器字长的指令称为双字长指令。
在一个指令系统中,若所有指令的长度都是相等的,则称为定长指令字结构。定字长指令的执行速度快,控制简单。若各种指令的长度随指令功能而异,则称为变长指令字结构。然而,因为主存一般是按字节编址的,所以指令字长多为字节的整数倍。
指令长度的不同会导致取指令时间开销的不同,单字长指令只需访存一次就能将指令完整取出;而双字长指令则需访存两次才能完整取出,耗费两个存取周期。
4)按操作码长度分类
5)按操作类型分类
转移指令有条件 / 无条件、直接 / 间接、相对 / 绝对三种属性。
-
条件转移是指需要先判断条件是否成立,才决定是否转移;无条件转移是指不用判断条件就可以转移,典型的是函数调用和返回。
-
直接转移是指转移目标地址直接放在指令中,执行时直接将地址码送入 PC;间接转移是指转移目标地址存放在寄存器或内存单元中。
-
相对转移是指转移目标地址为当前 PC 值加上偏移量,偏移量一般在指令中;绝对转移是指转移目标地址直接由指令或寄存器给出。
3. 定长操作码指令格式
定长操作码指令在指令字的最高位部分分配固定的若干位(定长)表示操作码。一般 n 位操作码字段的指令系统最大能够表示 2n 条指令。定长操作码对于简化计算机硬件设计,提高指令译码和识别速度很有利。当计算机字长为 32 位或更长时,这是常规用法。
4. 扩展操作码指令格式
【总结】:
为了在指令字长有限的前提下仍保持比较丰富的指令种类,可采取可变长度操作码,即全部指令的操作码字段的位数不固定,且分散地放在指令字的不同位置上。显然,这将增加指令译码和分析的难度,使控制器的设计复杂化。
最常见的变长操作码方法是扩展操作码,它使操作码的长度随地址码的减少而增加,不同地址数的指令可具有不同长度的操作码,从而在满足需要的前提下,有效地缩短指令字长。
在设计扩展操作码指令格式时,必须注意以下两点:
-
不允许短码是长码的前缀,即短操作码不能与长操作码的前面部分的代码相同。(对比哈夫曼树“前缀编码”)
-
各指令的操作码一定不能重复。
通常情况下,对使用频率较高的指令分配较短的操作码,对使用频率较低的指令分配较长的操作码,从而尽可能减少指令译码和分析的时间。
设地址长度为 n ,上一层留出 m 种状态,下一层可扩展出 m×2n 种状态。
设指令字长固定为 16 位,试设计一套指令系统满足:有 15 条三地址指令、有 12 条二地址指令、有 62 条一地址指令、有 32 条零地址指令。
OP | A1 | A2 | A3 |
---|---|---|---|
0000~1110 | A1 | A2 | A3 |
1111 | 0000~1011 | A2 | A3 |
1111 | 1100~1111 | 0000~1101 | A3 |
1111 | 1100~1111 | 1110~1111 | 0000~1111 |
二、指令的寻址方式
1. 指令寻址和数据寻址
【总结】:
寻址方式是指寻找指令或操作数有效地址的方式,即确定本条指令的数据地址及下一条待执行指令的地址的方法。采用不同寻址方式的目的是为了缩短指令字长,扩大寻址空间,提高编程的灵活性,但这也提高了指令译码的复杂度。
指令中的地址码字段并不代表操作数的真实地址,这种地址称为形式地址 (A) 。形式地址结合寻址方式,可以计算出操作数在存储器中的真实地址,这种地址称为有效地址 (EA) 。
注意,(A) 表示地址为 A 的数值, A 既可以是寄存器编号,也可以是内存地址。对应的 (A) 就是寄存器中的数值,或相应内存单元的数值。例如, EA = (A) 意思是有效地址是地址 A 中的数值。
寻址方式分为指令寻址和数据寻址两大类。寻找下一条将要执行的指令地址称为指令寻址;寻找本条指令的数据地址称为数据寻址。
1)指令寻址
指令寻址方式有两种:一种是顺序寻址方式,另一种是跳跃寻址方式。
① 顺序寻址:
通过程序计数器 PC 加 “1” (1 个指令字长),自动形成下一条指令的地址。
② 跳跃寻址:
通过转移类指令实现。所谓跳跃,是指下条指令的地址不由程序计数器 PC 自动给出,而由本条指令给出下条指令地址的计算方式。而是否跳跃可能受到状态寄存器和操作数的控制,跳跃的地址分为绝对地址(由标记符直接得到)和相对地址(相对于当前指令地址的偏移量),跳跃的结果是当前指令修改 PC 值,所以下一条指令仍然通过 PC 给出。
2)数据寻址
数据寻址是指如何在指令中表示一个操作数的地址,如何用这种表示得到操作数或怎样计算出操作数的地址。
数据寻址的方式较多,为区别各种方式,通常在指令字中设一个字段,用来指明属于哪种寻址方式,由此可得指令的格式为:
操作码 | 寻址特征 | 形式地址A |
---|
2. 常见的数据寻址方式
【总结】:
1)直接寻址(0010)
指令字中的形式地址为操作数的有效地址,这种方式为直接寻址。
2)间接寻址(0011)
间接寻址可以是一次间接寻址,还可以是多次间接寻址。
由于访问速度过慢,这种寻址方式并不常用。一般问到扩大寻址范围时,通常指的是寄存器间接寻址。
3)寄存器寻址(0100)
CPU 中寄存器的数量都不会太多,用很短的编码就可以指定寄存器,寄存器寻址需要的地址段位数为 ⌈log2(通用寄存器个数)⌉,因此能有效地缩短地址段的位数。
4)寄存器间接寻址(0101)
5)隐含寻址(0000)
例如,单地址的指令格式就不明显地在地址字段中指出第二操作数的地址,而规定累加器(ACC)作为第二操作数地址,指令格式明显指出的仅是第一操作数的地址。因此,累加器(ACC)对单地址指令格式来说是隐含寻址。
隐含寻址不明显给出操作数地址,而在指令中隐含操作数的地址,因此可以简化地址结构。
6)立即寻址(0001)
7)基址寻址(0111)
基址寻址、变址寻址、相对寻址都属于偏移寻址,区别在于偏移的“起点”不一样。
基址寻址:以程序的起始存放地址作为“起点”;EA = (BR) + A
变址寻址:程序员自己决定从哪里作为“起点”;EA = (IX) + A
相对寻址:以程序计数器PC所指地址作为“起点”。EA = (PC) + A
基址寄存器既可采用专用寄存器,又可采用通用寄存器。
8)变址寻址(1000)
显然,变址寻址与基址寻址的有效地址形成过程极为相似。但从本质上讲,两者有较大区别。
-
基址寻址面向系统,主要用于为多道程序或数据分配存储空间,因此基址寄存器的内容通常由操作系统或管理程序确定,在程序的执行过程中其值不可变,而指令字中的 A 是可变的;
-
变址寻址立足于用户,主要用于处理数组问题,在变址寻址中,变址寄存器的内容由用户设定,在程序执行过程中其值可变,而指令字中的 A 是不可变的。
9)基址&变址复合寻址
10)相对寻址(0110)
注意:取出当前指令后, PC 会指向下一条指令,相对寻址是相对于下一条指令的偏移
【拓展】:
11)堆栈寻址(1001)
堆栈可分为硬堆栈与软堆栈两种。
寄存器堆栈又称硬堆栈,寄存器堆栈的成本较高,不适合做大容量的堆栈;而从主存中划出一段区域来做堆栈是最合算且最常用的方法,这种堆栈称为软堆栈。
在采用堆栈结构的计算机系统中,大部分指令表面上都表现为无操作数指令的形式,因为操作数地址都隐含使用了 SP。通常情况下,在读/写堆栈中的一个单元的前后都伴有自动完成对 SP 内容的增量或减量操作。
三、小结
1、什么是指令?什么是指令系统?为什么要引入指令系统?
指令就是要计算机执行某种操作的命令。
一台计算机中所有机器指令的集合,称为这台计算机的指令系统。
引入指令系统后,避免了用户与二进制代码直接接触,使得用户编写程序更为方便。另外,指令系统是表征一台计算机性能的重要因素,它的格式与功能不仅直接影响到机器的硬件结构,而且也直接影响到系统软件,影响到机器的适用范围。
2、一般来说,指令分为哪些部分?每部分有什么用处?
一条指令通常包括操作码字段和地址码字段两部分。
其中,操作码指出指令中该指令应该执行什么性质的操作和具有何种功能,它是识别指令、了解指令功能与区分操作数地址内容的组成和使用方法等的关键信息。
地址码用于给出被操作的信息(指令或数据)的地址,包括参加运算的一个或多个操作数所在的地址、运算结果的保存地址、程序的转移地址、被调用子程序的入口地址等。
3、对于一个指令系统来说, 寻址方式多和少有什么影响?
寻址方式的多样化能让用户编程更为方便,但多重寻址方式会造成 CPU 结构的复杂化(详见下章),也不利于指令流水线的运行。
而寻址方式太少虽然能够提高 CPU 的效率,但对于用户而言,少数几种寻址方式会使编程变得复杂,很难满足用户的需求。
4、简述各常见指令寻址方式的特点和适用情况。
-
立即寻址操作数获取便捷,通常用于给寄存器赋初值。
-
直接寻址相对于立即寻址,缩短了指令长度。
-
间接寻址扩大了寻址范围,便于编制程序,易于完成子程序返回。
-
寄存器寻址的指令字较短,指令执行速度较快。
-
寄存器间接寻址扩大了寻址范围。
-
基址寻址扩大了操作数寻址范围,适用于多道程序设计,常用于为程序或数据分配存储空间。
-
变址寻址主要用于处理数组问题,适合编制循环程序。
-
相对寻址编制程序时,无须指定绝对地址,只需确定程序内部的相对距离,从而可以使用浮动地址,给程序的重定位带来了方便,便于实现多道程序,常用于控制程序的执行顺序、转移等。
基址寻址和变址寻址的区别:两种方式有效地址的形成都是寄存器内容+偏移地址,但是在基址寻址中,程序员操作的是偏移地址,基址寄存器的内容由操作系统控制,在执行过程中是动态调整的;而在变址寻址中,程序员操作的是变址寄存器,偏移地址是固定不变的。
5、一个操作数在内存可能占多个单元,怎样在指令中给出操作数的地址?
现代计算机都采用字节编址方式,即一个内存单元只能存放一字节的信息。一个操作数(如 char 、int、float、double) 可能是 8 位、16 位、32 位或 64 位等,因此可能占用 1 个、2 个、4 个或 8 个内存单元。也就是说,一个操作数可能有多个内存地址对应。
有两种不同的地址指定方式:大端方式和小端方式。
-
大端方式:指令中给出的地址是操作数最高有效字节(MSB)所在的地址。
-
小端方式:指令中给出的地址是操作数最低有效字节(LSB)所在的地址。