指令系统
指令又称为机器指令,是指示计算机执行某种操作的命令,一台计算机所有指令的集合构成该机的指令系统,也称指令集。
指令格式
指令是一组有意义的二进制代码,通常包括操作码字段和地址码字段。根据地址个数,又分为零地址指令,一地址指令,二地址指令等。
操作码指出该指令应该执行什么操作,具有什么功能,地址码给出被操作的信息的地址。
指令字长是指一条指令所包含的二进制代码的位数,取决于操作码的长度、地址码的长度和地址码的个数。指令字长和机器字长没有固定的关系,可以大于,可以等于,可以小于。
一般可以根据指令字长将指令分为半字长指令、单字长指令、双字长指令。指令字长也会影响取指令的时间开销,单字长指令只需要一次访存就能将指令完整取出,而双字长指令需要两次。
零地址指令
只给出操作码,没有显式地址。有些指令不需要操作数,比如空操作指令、停机指令或者关中断指令等,也有在堆栈计算机中的一些运算类指令,会将操作数利用堆栈存取,不需要给出地址。
一地址指令
一地址指令一般就两种情况
- 只有目的操作数的单操作数指令,按地址码读取操作数后,操作完成将结果存回原地址
- 隐含阅读的目的地址的双操作指令,比如累加器累加,最后运算结果会存放在累加器中
二地址指令
给出两个操作数,并指令目的操作数和源操作数,并将运算结果保存至目的操作数的地址。
三地址指令
在二指令的基础上,给出结果存放的地址,将运算结果写到指明的目的地址。
四地址指令
在三地址的基础上给出下一条指令的地址。
指令的寻址方式
寻找下一条执行的指令的地址称为指令寻址,寻找本条指令的数据地址称为数据寻址。
指令寻址
通过程序计数器 PC 加 1(1 指的是一条指令的长度),自动形成下一条指令的地址,这种寻址方式称为顺序寻址。
也有一些跳转指令,下一条指令的地址并不是按照顺序来的,而是通过本条指令计算出下一条指令的地址,跳跃的方式分为绝对转移方式(地址码由指令直接给出)和相对转移方式(地址码指出转移目的地址相对于当前 PC 的偏移量),这种寻址方式称为跳跃寻址。
数据寻址
数据寻址的方式较多,为了区别各种方式,通常会在指令字中设置一个寻址特征字段,用来指明属于哪种寻址方式。
地址格式:操作码 | 寻址特征 | 形式地址
直接寻址
形式地址给出的就是操作数的真实地址,优点是简单,不需要专门的计算操作数的地址,指令在执行过程中也只要访存一次,但也有缺点,就是 A 的位数限制了操作数的寻址范围,操作数的地址不易修改。
间接寻址
间接寻址是相对于直接寻址而言,形式地址给出的并不是操作数的地址,而是存有操作数有效地址所在的主存单元的地址,也就是操作数地址的地址。优点是扩大了寻址的范围,缺点是需要多次访存。
寄存器寻址
形式地址给出的是寄存器的编号,寄存器中存放的操作数。
寄存器间接寻址
形式地址给出的是寄存器的编号,寄存器中存放的是操作数的地址。比一般的间接寻址要快。
隐含寻址
操作数不会显式的指出而是隐含的约定,比如前面提到过的累加寄存器。
立即寻址/立即数寻址
形式地址给出的就是操作数。优点是不需要访存,缺点就是 A 大小受限。
相对寻址
形式地址给出的是偏移量,基准是程序计数器 PC。
基址寻址
形式地址给出的是偏移量,基准是基址寄存器 BR。寄存器由操作系统管理,一般不可由用户改变。
变址寻址
形式地址给出的是偏移量,基准是变址寄存器 IX。寄存器是面向用户的,内容由用户设定。
堆栈寻址
堆栈式存储器中一块特定的按后进先出原则管理的存储区,存储区的读/写单元地址用一个特殊的寄存器给出(堆栈指针 SP)。在采用堆栈结果的计算机中,大部分指令都是零地址指令,因为操作数地址都隐含的使用了 SP。
指令操作码编码
指令的操作码可以是固定长度也可以是可变长度,定长操作码和变长操作码的选择是时间和空间权衡的问题。希望降低空间开销时,应当尽量缩短代码长度,应采用紧凑的变长操作码和变长指令字,但这样也会为译码带来时间开销,反之亦然。
定长操作码编码
采用定长操作码的指令操作码部分是固定长度,这种方式译码方便,指令执行速度快,但是存在信息冗余。例如下图所示的 IBM 306/370 指令集采用 8 位定长操作码,最多可有 256 条指令但是指令系统只提供了 183 条指令,有 73 种为冗余编码。
扩展操作码编码
扩展操作码编码方式讲操作码的编码方式分成几种固定长度的格式,可以采用等长扩展法即 4-8-12-16 这种等长的方式扩展,目前这种编码方式被广泛使用。
举一个扩展操作码的具体例子,设某个指令系统的指令字长为 16 位,每个地址码为 6 为若二地址指令有 15 条,一地址指令有 34 条,问剩下的零地址指令最多可以有多少条。
二地址指令地址码部分占 12 位,操作码有四位,一共 15 条二地址指令,可将 0000-1110 分配给二地址指令。剩下的 1111 就给扩展后的一地址指令使用。一地址指令多了 6 位用来表示操作码且用 34 条,(1111 000000 ~ 1111 011111 和 1111 100000 ~ 1111 100001)。剩下的零地址指令在前 10 位还剩$1111111111 - 1111100001$ 种编码即 30 种,在加上新增的位数就是 30*2^6 种编码。
指令操作类型
指令系统的完备性要求在设计指令系统是必须考虑指令系统应提供哪些操作。一般分为一下几种:
- 算术和逻辑运算指令,这类指令有加减乘除与或非异或自增自减等。
- 移位指令,这类指令提供算术移位、逻辑移位、循环移位、半字交换等,有的机器默认只移一位,如果要移位多位的话就需要多条移位指令。
- 传送指令,传送指令通常用寄存器之间的传送(MOV)、从内存读取到 cpu 寄存器(LOAD)、从 CPU 写道内存单元(STORE)等。
- 串指令,针对串进行操作,比如串比较,串检索等。
- 顺序控制指令,用来控制指令的执行顺序,比如有条件转移指令、无条件转移指令、跳步、调用、返回等。
- CPU 控制指令,比如停机、开中断、关中断、系统模式切换等,大多数机器也将这类指令划为特权指令。
- 输入输出指令。
CISC 和 RISC
CISC 风格指令系统
随着 VLSI 技术的迅速发展,计算机硬件的成本不断下降,软件成本不断上升,为此人们在设计指令系统的时候增加了越来越多功能强大的复杂指令,使得机器指令的功能接近高级语言语句的功能,给软件提供更好的支持。
CISC 风格指令系统的主要特点有:
- 指令系统复杂,指令多,寻址方式多,指令格式多。
- 指令周期长,绝大多数指令需要多个时间周期才能完成。
- 指令周期差距大,各种指令都能访问存储器,使得简单指令和复杂指令所用时间差距很大。
- 采用微程序控制,由于有些指令非常复杂,以至于无法用硬布线的方式实现,而采用微程序的思想来实现硬件,可以实现对复杂指令的控制。
- 难以进行编译优化,由于编译器可选的指令序列增多,使得目标代码组合增加,从而增加了目的代码优化的难度。
复杂的指令系统使得计算机的结构也越来越复杂,不仅增加了研制周期和成本,而且难以保证其正确性,甚至降低了性能。
RISC 风格指令系统
RISC 的着眼典不是简单地放在简化指令系统上,而是通过简化指令使计算机结构更加简单合理,从而提高机器性能。与 CISC 相比,RISC 有一下特点:
- 指令数目少,只包含使用频度高的简单指令。
- 指令格式更加规整,寻址方式少,指令格式少,指令长度一致。
- 采用 Load/Store 型指令设计风格。
- 采用流水线方式执行指令。
- 采用大量通用寄存器。
- 采用硬布线控制方式
- 采用优化的编译系统。指令数有利于编译器的优化。
采用 RISC 后,由于指令系统简单,CPU 控制逻辑大大简化,芯片上可以设置更多的通用寄存器,指令也可以采用速度较快的硬布线控制器来控制,且更适合采用指令流水线技术,使指令执行效率进一步提高。
指令流水线
一条指令的执行过程可以被分成若干执行阶段,每个阶段由相应的功能部件完成,如果各个阶段看成相应的流水段,则指令的执行过程就构成了一条指令流水线。