1.指令格式
指令(又称机器指令),是指示计算机执行某种操作的命令是计算机运行的最小功能单位。一台计算机的所有指令的集仑构成该机的指令系统,也称为指令集。
注:一台计算机只能执行自己指令系统中的指令,不能执行其他系统的指令。
一条指令通常要包括操作码字段和地址码字段两部分:
一条指令可能包含 0个、1个、2个、3个、4个地址码....
根据地址码数目不同,可以将指令分为零地址指令、一地址指令、二地址指令...
2.按地址码数目分类
(1)零地址指令
1.不需要操作数,如空操作、停机、关中断等指令
2.堆栈计算机,两个操作数隐含存放在栈顶和次栈顶,计算结果压回栈顶,例如“后缀表达式”
在栈的操作。
如上图所示,当扫描到“+”符号时,就会把栈顶和次栈顶两个元素执行相应运算,将运算结果压回栈顶,再继续往后扫描。
(2)一地址指令
1.只需要单操作数,如加1、减1、取反、求补等
指令含义:OP(A1)--->A1 完成一条指令需要3次访存:取指--->读A1(读A1对应的主存单元)--->写A1(得到运算结果后,会把运算结果再次写回A1)
2.需要两个操作数,但其中一个操作数隐含在某个寄存器(如隐含在ACC)
指令含义:(ACC)OP(A1)--->ACC 完成一条指令需要2次访存:取指--->读A1(由于最终结果保存在ACC中,所以存结果不需要访存)
注:A1指某个主存地址,(A1)表示A1所指向的地址中的内容,A1可以类比C语言中的指针,(A1)可以类比指针所指位置的内容。
(3)二地址指令
常用于需要两个操作数的算术运算、逻辑运算相关指令
指令含义:(AI)OP(A2)--->A1 完成一条指令需要访存4次,取指--->读A1 --->读A2--->写A1
(4)三地址指令
常用于需要两个操作数的算术运算、逻辑运算相关指令
指令含义:(AI)OP(A2)→A3 完成一条指令需要访存4次,取指--->读A1 --->读A2--->写A3
(5)四地址指令
指令含义:(A1)OP(A2)--->A3,A4 =下一条将要执行指令的地址
完成一条指令需要访存4次,取指---> 读A1 ---> 读A2 ---> 写A3
注:正常情况下取指令之后PC+1,指向下一条指令,对于四地址指令而言,执行指令后,将PC的值修改为A4所指地址
n位地址码的直接寻址范围=2^n,若指令总长度固定不变,则地址码数量越多,寻址能力越差。
3.按指令长度分类
指令字长:一条指令的总长度(可能会变)
机器字长:CPU进行一次整数运算所能处理的二进制数据的位数(通常和ALU直接相关)
存储字长:一个存储单元中的二进制代码位数(通常和MDR位数相同)
半字长指令、单字长指令、双字长指令---指令长度是机器字长的多少倍
指令字长会影响取指令所需时间。如:机器字长=存储字长=16bit,则取一条双字长指令(32bit)需要两次访存
定长指令字结构:指令系统中所有指令的长度都相等
变长指令字结构:指令系统中各种指令的长度不等
4.按操作码长度分类
定长操作码:指令系统中所有指令的操作码长度都相同,若操作码固定为n位,表示这个系统最多能支持2^n条指令。
对于定长操作码指令系统,控制器的译码电路设计简单,但灵活性较低
优点:定长操作码对于简化计算机硬件设计,提高指令译码和识别速度很有利;
缺点:指令数量增加时会占用更多固定位,留给表示操作数地址的位数受限。
可变长操作码:指令系统中各指令的操作码长度可变,对于可变长操作码指令系统,控制器的译码电路设计复杂但灵活性较高
若定长指令字结构+可变长操作码----扩展操作码指令格式,即不同地址数的指令使用不同长度的操作码
•扩展操作码
全部指令的操作码字段的位数不固定,且分散地放在指令字的不同位置上。最常见的变长操作码方法是扩展操作码,使操作码的长度随地址码的减少而增加,不同地址数的指令可以具有不同长度的操作码,从而在满足需要的前提下,有效地缩短指令字长。
举个例子:
若指令长度为16位,并且每个地址码占4位,若设置三地址指令,则地址码总共占3*4=12位 ,剩余4位来表示操作码,4位基本操作码若全部用于三地址指令,则有16(2^4)条。但至少须将1111留作扩展操作码之用,即三地址指令为15条
1111 1111留作扩展操作码之用,二地址指令为15条;CPU取得一条指令时,会直接读入16位,CPU根据开头4位是否为全1,判断是三地址指令或二地址指令,若开头4位是1111,后4位不为全1,则为二地址指令
同理,后4位为全1保留下来,作为一地址指令,一地址指令为15条,若前8位全为1,则为一地址指令
最后4位为0000~1111,前面12位全为1,因为已经不需要拓展了,所以零地址指令为16条
当然还有其他扩展操作码设计方法,这里只是其中一种。
所以在设计扩展操作码指令格式时,必须注意以下两点:
(1) 不允许短码是长码的前缀,即短操作码不能与长操作码的前面部分的代码相同。
例如上面例子,二地址指令操作码为前8位,为长码,三地址指令的操作码为前4位,为短码,不允许短码是长码的前缀的含义为:这4位操作码不能为全1
(2)各指令的操作码一定不能重复。
通常情况下,对使用频率较高的指令,分配较短的操作码;对使用频率较低的指令,分配较长的操作码,从而尽可能减少指令译码和分析的时间。
再举一例扩展操作码的示例:
设指令字长固定为16位,若需要15条三地址指令,会留下1111作为扩展操作码:
需要12条二地址指令,则前4位为1111,紧接着后面4位为0000(0)~1011(11)总共12条
需要62条一地址指令,则黑框部分用于表示0~61,即用6位地址表示:000000~111101
需要32条零地址指令,最后5位刚好能表示0~31
按照上面的扩展操作码的设计,若CPU访问的指令最前4位不为全1,则说明这是一条三地址指令
若前4位为全1,再判断紧接着后面2位是否为1,若不为全1,则为二地址指令,若为全1,那么会继续检测后面紧跟的5位是否全为1,若不是,则为一地址指令,若是,则为零地址指令
对扩展操作码而言,若地址长度为n,上一层留出m种状态,下一层可扩展出 mx2^n 种状态
例如,对于三地址指令,需要用前4位表示操作码,表示2^4=16种状态,留出16-15=1种状态作为下一层的扩展
对于下一层的二地址指令而言,可以用1111+紧接着后4位的信息,表示这是哪一种状态的指令,2^4=16,而上一层留下的扩展状态为1种,所以总共能表示的状态为1*2^4=16种,而只需要12条二地址指令,所以16-12=4种状态会留到下一层
对于下一层的一地址指令而言,就有4*2^4=64种状态,所以会留出64-62=2种状态到下一层
对于零地址指令而言,就有2*2^4=32种状态
扩展操作码的特点:
优点:在指令字长有限的前提下仍保持比较丰富的指令种类;
缺点:增加了指令译码和分析的难度,使控制器的设计复杂化。
5.按操作类型分类
数据传送类:进行主存与CPU之间的数据传送
1.数据传送
LOAD作用:把存储器(源)中的数据放到寄存器(目的)中
STORE作用:把寄存器中的数据放到存储器中
运算类:
2.算术逻辑操作
算术:加、减、乘、除、增 1、减 1、求补、浮点运算、十进制运算
逻辑:与、或、非、异或、位操作、位测试、位清除、位求反
3.移位操作
算术移位、逻辑移位、循环移位(带进位和不带进位)
程序控制类:改变程序执行的顺序
4.转移操作
无条件转移 JMP
条件转移 JZ:结果为0;JO:结果溢出;JC:结果有进位
调用和返回 CALL和RETURN
陷阱(Trap)与陷阱指令
注:执行这一类的指令会导致程序计数器(PC)的值改变
输入输出类(I/O):进行CPU和I/O设备之间的数据传送
5.输入输出操作
CPU寄存器与IO端口之间的数据传送(端口即IO接口中的寄存器)
6.指令寻址
计算机在执行指令时,是如何确定下一条指令的存放地址的呢?
(1)顺序寻址
对于定长指令字结构:
对于PC程序计数器,始终指向下一条指令的存放地址,若该系统采用定长指令字结构,指令字长存储字长=16bit=2B,主存按字编址,这样CPU每取走一条指令,只需要简单地给PC+1即可。
若该系统采用定长指令字结构,指令字长储字长=16bit=2B,主存按字节编址,这就意味着每一条指令占2个指令地址,那么程序计数器欲指向下一条指令的地址的话就需要:(PC)+2--->PC
对于变长指令字结构:
如图所示,具有相同颜色的存储字为1条指令,不同指令的指令字长不同,由于CPU无法确定当前指向的指令占多少存储字,在这种情况下,CPU会先读入一个字,根据操作码判断这条指令的总字节数n,修改PC的值。(PC)+n--->PC
根据指令的类型,CPU可能还要进行多次访存,每次读入一个字
(2)跳跃寻址
该系统采用定长指令字结构,指令字长=存储字长=16bit=2B,主存按字编址
如图所示,当执行到JMP指令时,同样会使得PC的值会自动+1,但是CPU执行指令时发现这是一条无条件转移指令, 下图中JMP对应的7表示的是下一条执行的指令存放在什么位置,类似于C语言中的goto语句,执行这条转移指令,PC的值将会修改为7,改变了程序的执行流,接下来,CPU会跳转到PC所指的位置继续执行指令。
7.数据寻址
在指令寻址中,解决了如何确定下一条 欲执行 指令 的 指令地址的问题,即始终由程序计数器PC给出。
而数据寻址则需要确定本条指令的地址码指明的真实地址。
若需要运行的程序是从主存地址为100的位置开始存储,若依然按照之前的方式解读地址码7,那么需要跳转到主存地址为7的位置,但实际上,应该跳转到主存地址为107的位置。这里的7我们可以理解为起始地址往后的偏移量
对于下图,我们又该如何理解?当CPU读取103主存地址的指令时,PC会自动+1,这里的3表示从PC所指的这个位置往后偏移3个地址,所以104+3=107,即下一条指令的地址
所以数据寻址方式有很多种:
为了区分是由哪种方式寻址,,通常会在地址码前,加入寻址方式位,来区分不同寻址方式:
对于一地址指令,形式地址根据不同的寻址方式解读,得到最终真实的地址,真实地址也称为有效地址(EA)
对于多指令地址,由于每个地址的寻址方式可能不同,所以会在每个形式地址前加入寻址方式位,用来区分不同的寻址方式:
这里我们以一地址指令为例,来讲解数据寻址方式,并且假设指令字长=机器字长=存储字长,操作数为3:
(1)直接寻址
对于直接寻址,结构如下:
中间的4位数用于表示采用的是直接寻址方式,而指令字中的形式地址A就是操作数的真实地址EA,即EA=A。
这条取数指令执行的结果就是从CPU指明的地址中取数,并且存放到ACC中,如下图所示,要存放到操作数3,就直接存放在A指向的地址中
这条指令的执行一共需要2次访存,取指令需要访存1次,执行指令也需要访存1次
优点:简单,指令执行阶段仅访问一次主存,不需专门计算操作数的地址。
缺点:A的位数决定了该指令操作数的寻址范围。并且操作数的地址不易修改,若操作数寻址地址发生改变,那么这条指令指明的地址就会失效,即指向错误的主存地址,除非修改指令中的地址。
2)间接寻址
指令的地址字段给出的形式地址不是操作数的真正地址,而是操作数有效地址所在的存储单元的地址,也就是操作数地址的地址,即EA=(A)
如图所示,形式地址A指向的主存单元中存储了CPU需要访问的操作数的真实地址,也就是形式地址A指向的也是一个地址,这个地址是操作数真实地址。
采用这种寻址方式,执行一条指令需要3次访存,取指令需要执行访存1次,执行指令需要访存2次(第一次访存得到操作数的真实地址,第二次访存得到操作数)
这种方法具体的是一次间接寻址,当然也存在两次间接寻址,如下图所示中,存储单元的第一个bit位表示的是这一存储单元中存放的地址是否是操作数存放的地址,1表示这个存储单元中存放的地址不是操作数的真实地址,0表示这个存储单元中存放的地址是操作数的真实地址,那么他指向的存储单元中存放的就是操作数
优点:可扩大寻址范围(有效地址EA的位数大于形式地址A的位数)。
例如,对于直接寻址,若形式地址有16位,那么操作数只能存放在0~(2^16)-1范围中,但是若采用间接寻址,A所指的地址单位EA中可以存更长的数据,例如32位数据,那么最终的数据可以存放的地址范围就为0~(2^32)-1
便于编制程序(用间接寻址可以方便地完成子程序返回)。
缺点:指令在执行阶段要多次访存(一次间址需两次访存,多次寻址需根据存储字的最高位确定几次访存)。会导致指令执行效率降低。
计算机组成原理(5)----指令系统(2):https://developer.aliyun.com/article/1511500