计算机组成原理(5)----指令系统

目录

1.指令格式

2.按地址码数目分类

(1)零地址指令

(2)一地址指令

(3)二地址指令

(4)三地址指令

(5)四地址指令

3.按指令长度分类

4.按操作码长度分类

•扩展操作码

5.按操作类型分类

6.指令寻址

(1)顺序寻址

(2)跳跃寻址

7.数据寻址

(1)直接寻址

(2)间接寻址

(3)寄存器寻址

(4)寄存器间接寻址

(5)隐含寻址

(6)立即寻址

偏移寻址:

(7)基址寻址

(8)变址寻址

(9)基址+变址复合寻址

(10)相对寻址

(11)堆栈寻址

•硬堆栈

•软堆栈

8.CISC和RISC

(1)CISC(Complex instruction Set Computer)

(2)RISC(Reduced instruction Set Computer)


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条三地址指令:对于三地址指令而言,需要12位作为地址码,只用前4位(16-12=4)表示操作码,0000~1110表示操作码,1111表示扩展操作码:

需要12条二地址指令,则前4位为1111,二地址指令需要8位地址码,所以只能由中间4位表示操作码:0000(0)~1011(11)总共12条。我们会发现,剩余1100,1101,1110,1111没有对应的操作码,这些位都是以“11”开头的,所以如果开头为1111 11则表示超出了二地址指令的范围。

一地址指令只需要保留最后的4位作为地址码。需要62条一地址指令,则可以用剩下的6位,即黑框部分表示不同的一地址指令:000000(0)~111101(61)。同理,最大的能表示一地址指令的数为:1111 1111 1101 xxxx,如果超出了这一范围,即1111 1111 1110 xxxx,前面11位都为“1”,那么就超出了一地址指令的合法范围。

需要32条零地址指令,剩下的5位刚好能表示00000(0)~11111(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种状态

定长操作码和扩展操作码的对比:

定长操作码:在指令字的最高位部分分配固定的若干位(定长)表示操作码。

一般n位操作码字段的指令系统最大能够表示2^n条指令。

优:定长操作码对于简化计算机硬件设计,提高指令译码和识别速度很有利;

缺:指令数量增加时会占用更多固定位,留给表示操作数地址的位数受限。


扩展操作码(不定长操作码):全部指令的操作码字段的位数不固定,且分散地放在指令字的不同位置上。

最常见的变长操作码方法是扩展操作码,使操作码的长度随地址码的减少而增加,不同地址数的指令可以具有不同长度 的操作码,从而在满足需要的前提下,有效地缩短指令字长

优:在指令字长有限的前提下仍保持比较丰富的指令种类;

缺:增加了指令译码和分析的难度,使控制器的设计复杂化。

例题1:

设计某指令系统时,假设采用 16 位定长指令字格式,操作码使用扩展编码方式,地址码为6位,包含零地址,一地址和二地址3种格式的指令,若二地址指令有12条,一地址指令有254条,则零地址指令的条数最多为()

A.0        B.2        C.64        D.128

答案:D

先分析一下:

二地址指令占12(2*6=12)位地址空间,4位用来表示操作码,二地址指令有12条,那么剩余16-12=4条操作码扩展给一地址指令。

0000~1011  xxxx xxxx xxxx

一地址指令格式为,:

11xx xxxx xxxx xxxx,其中低6位为地址码,一地址指令有254条,那么一地址指令可表示的范围:

1100 0000 00xx xxxx~1111 1111 01xx xxxx

其中,00 0000 00~11 1111 01表示0~253,总共254条指令。剩余256-254=2条指令扩展给零地址指令。

1111 1111 1xxx xxxx,前9位固定,因为超过1111 1111 01xx xxxx,就是零地址能表示的范围了。剩余位为16-9=7。所以零地址指令的条数最多为2^7=128条。

当然可以直接用刚刚讲的公式:

二地址指令有12条,则剩余16-12=4种操作码给一地址指令,一地址指令有254条,4*2^6-254=2种操作码给零地址指令,所以零地址指令一共有2*2^6=128条。

还可以这么想:

地址码为6位,一条二地址指令会占用2^6条一地址指令的空间,一条一地址指令会占用2^6条零地址指令的空间。若全都是零地址指令,则最多有2^16条,减去一地址指令和二地址指令所占用的零地址指令空间,即2^16-254x2^6-12x2^6x2^6=128。

例题2:

某计算机按字节编址,指令字长固定且只有两种指令格式,其中三地址指令29条、二地址指令107条,每个地址字段为6位,则指令字长少应该是()

A.24位        B.26位        C.28位        D.32位

分析:三地址指令有29条,需要至少5位操作码,最后会剩余:2^5=32 ,32-29=3种操作码扩展给二地址指令,而二地址额外多了6位操作码(地址码比三地址指令少6位),所以数量最大达到3*64=192条。所以指令字长最少为5+6+12=23位。

又因为计算机按字节编址,需要8的倍数,所以指令字长至少为24位。

答案:A

5.按操作类型分类

数据传送类:进行主存与CPU之间的数据传送

1.数据传送
LOAD作用:把存储器(源)中的数据放到寄存器(目的)

STORE作用:把寄存器中的数据放到存储器中

运算类:

2.算术逻辑操作

算术:加、减、乘、除、增 1、减 1、求补、浮点运算、十进制运算

逻辑:与、或、非、异或、位操作、位测试、位清除、位求反

3.移位操作

算术移位、逻辑移位、循环移位(带进位和不带进位)

程序控制类:改变程序执行的顺序

4.转移操作
无条件转移     JMP

条件转移        JZ:结果为0;JO:结果溢出;JC:结果有进位

调用和返回 CALL和RETURN

陷阱(Trap)与陷阱指令

注:执行这一类的指令会导致程序计数器(PC)的值改变

有条件/无条件转移只是转移指令的一种属性:

转移指令有条件/无条件、直接/间接、相对/绝对三种属性。

条件转移是指需要先判断条件是否成立,才决定是否转移;无条件转移是指不用判断条件就可以转移,典型的是函数调用和返回。

直接转移是指转移目标地址直接放在指令中,执行时直接将地址码送入PC;间接转移是指转移目标地址存放在寄存器或内存单元中。

相对转移是指转移目标地址为当前 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

便于编制程序(用间接寻址可以方便地完成子程序返回)。

缺点:指令在执行阶段要多次访存(一次间址需两次访存,多次寻址需根据存储字的最高位确定几次访存)。会导致指令执行效率降低。

(3)寄存器寻址

在指令字中直接给出操作数所在的寄存器编号,即EA=Ri,其操作数在由Ri所指的寄存器内。

采用这一寻址方式,执行一条指令时,只需要1次访存,即取指令时,访存1次,执行指令时,只需要访问寄存器,而不需要访存。

优点:指令在执行阶段不访问主存,只访问寄存器,指令字短且执行速度快(CPU中寄存器数量较少,那么只需要使用较短的bit位,就可以表示所有寄存器的编号),支持向量/矩阵运算。

缺点:寄存器价格昂贵,计算机中寄存器个数有限,则寻址能力有限。

(4)寄存器间接寻址

寄存器Ri中给出的不是一个操作数,而是操作数所在主存单元的地址,即EA=(Ri)。

采用这种寻址方式,执行一条指令需要2次访存,取指令需要访存1次,执行指令也需要访存1次。

特点:与一般间接寻址相比速度更快(因为操作数的真实地址存放在寄存器中,而非主存中),但指令的执行阶段需要访问主存(因为操作数在主存中)。

(5)隐含寻址

不是明显地给出操作数的地址,而是在指令中隐含着操作数的地址。

例如,有些指令显式地给出的地址只是指明了其中一个操作数,而另一个操作数则隐含在ACC(累加寄存器)中,也就是这个操作数的地址没有在指令中显式指出。

优点:有利于缩短指令字长。
缺点:需增加存储操作数或隐含地址的硬件。

(6)立即寻址

对于立即寻址,形式地址A就是操作数本身,又称为立即数,一般采用补码形式。

#表示立即寻址特征

这里和直接寻址做区分,直接寻址的形式地址A表示的是操作数的地址,而立即寻址形式地址A就是操作数本身。

采用这种寻址方式,只需要进行1次访存,即取指令时访存1次,而我们需要的操作数直接包含在指令中,所以执行指令时不需要访存。

优点:指令执行阶段不访问主存,指令执行时间最短
缺点:A的位数限制了立即数的范围。如A的位数为n,且立即数采用补码时,可表示的数据范围为-2^{n-1} ~ 2^{n-1}-1

偏移寻址:

 接下来讲解的是"相对寻址","基址寻址","变址寻址",这三种寻址方式都可以归为"偏移寻址",因为这三个寻址方式的区别在于偏移的"起点"不一样。

基址寻址:以程序的起始存放地址作为“起点”,再加上形式地址A作为偏移量

变址寻址:程序员自己决定从哪里作为“起点”,再加上形式地址A作为偏移量

相对寻址:以程序计数器PC所指地址作为“起点”,再加上形式地址A作为偏移量

(7)基址寻址

将CPU中基址寄存器(BR)的内容加上指令格式中的形式地址A(由算数逻辑单元(ALU)进行加法运算),而形成操作数的有效地址,即EA=(BR)+A。

注:在操作系统中的“重定位寄存器”就是“基址寄存器”

在有些计算机中,不会专门设置“基址寄存器”,而是会用通用寄存器,可以在指令中指明,要将哪个通用寄存器作为基址寄存器使用。

如下图所示,指令的“寻址特征”用来表明用基址寻址的寻址方式,同时还需要几位来指明要将哪个通用寄存器作为基址寄存器使用(要用几个bit位,就需要根据寄存器总数判断,假如通用寄存器有8个,则只需要3bit即可,2^3=8)。图中使用通用寄存器R0,那么就会将R0中的地址作为基地址送到加法器中,同时将形式地址A作为偏移量送到加法器中,ALU通过加法运算得到最终的操作数存放地址。

基址寻址的作用:

若某段程序的起始地址不为0,那么可以采用基址寻址,将程序的起始地址+形式地址(偏移量),得到操作数的地址。

所以基址寻址便于程序浮动,方便实现多道程序并发运行。

当某程序在程序中的位置发生改变,操作系统只需要修改BR这一寄存器的内容即可。让BR指向当前程序的起始地址,那么即使该程序浮动,也不需要更改。

注:程序运行前,CPU将BR的值修改为程序的起始地址(这一地址信息存放在操作系统PCB中)

基址寄存器是面向操作系统的,其内容由操作系统或管理程序确定。在程序执行过程中,基址寄存器的内容不变(作为基地址),形式地址可变(作为偏移量)。

普通程序员可以用汇编语言修改通用寄存器的内容,但若某一通用寄存器被指定为基址寄存器,可由用户决定哪个寄存器作为基址寄存器,但其内容仍由操作系统确定。

优点:可扩大寻址范围(基址寄存器的位数大于形式地址A的位数);用户不必考虑自己的程序存于主存的哪一空间区域,故有利于多道程序设计,以及可用于编制浮动程序(整个程序在内存里边的浮动)

对于某条指令,形式地址A可能较短,寻址能力有限,但是在加上较长的基址地址,那么这一条指令可以访问的地址范围就能扩大。

(8)变址寻址

有效地址 EA 等于指令字中的形式地址A与变址寄存器IX的内容相加之和,即EA=(IX)+A,其中IX可为变址寄存器(专用),也可用通用寄存器作为变址寄存器

下图所示,左图为变址寻址,右图为基址寻址,除了寄存器不同,还有什么区别?

在基址寻址中,BR保持不变作为基地址,A作为偏移量

变址寄存器是面向用户的,在程序执行过程中,变址寄存器的内容可由用户改变(IX作为偏移量),形式地址A不变(作为基地址)

为什么?如果变的部分放在A中,意味着每进行一条指令就需要访存取A,如果变的是变址寄存器,它本身就在CPU内部,可以很快访问。

所以变址寻址适合用来访问数组,下面讲到的相对寻址适合用来实现跳转。

变址寻址的作用:

如图所示,对于循环类的程序,每一次循环都需要对应一条指令,这样的编程方式很不灵活。

所以需要引入变址寻址,则同样的程序执行流程如下:

从主存地址为2的位置开始说明

① ACC加法采用了变址寻址,EA=(IX)+A,这条指令的形式地址A指向了7这一主存地址,也就是数组第一个元素的存放地址,而变址寄存器IX的值为0,所以

(ACC)+(7+(IX))-->ACC        所以(ACC)=a[0]

接下来进行IX加法,也就相当于程序中的i++,再将IX与10进行比较,对应于程序的:

for(int i=0;i<10;i++)

若i<10,则程序的执行流,跳转到主存地址为2的位置,即进行第二次的加法,由于现在IX=1,所以操作数放在(7+1)=8的位置,即a[1]的地址。

那么(ACC)+(7+(IX))-->ACC        (ACC)=a[0]+a[1]

若i=10,那么就不会条件跳转,而是执行ACC--->sum变量,即将所有数组之和赋值给sum变量

所以在数组处理过程中,可设定A为数组的首地址,不断改变变址寄存器IX的内容,便可很容易形成数组中任一数据的地址,特别适合编制循环程序。

这里补充硬件是如何实现数的“比较”? 

1.通过"cmp指令"比较a和b(如cmp a,b),实质上是用 a-b

2.相减的结果信息会记录在程序状态字寄存器(PSW)中

信息如下,PSW中有几个比特位记录上次运算的结果:

进位/借位标志CF:最高位有进位/借位时CF=1

零标志 ZF:运算结果为0则ZF=1,否则ZF=0

符号标志SF:运算结果为负,SF=1,否则为0

溢出标志OF:运算结果有溢出OF=1,否则为0

3.CPU根据PSW的某几个标志位进行条件判断,来决定是否转移

举个例子:

如下图所示,记录a-b的结果,若a<b,零标志位ZF=0,符号标志位SF=1,硬件电路以这两个bit位作为输入信号,通过电路处理,将PC的值指向else所对应的第一条指令,这就完成了条件转移。

注:汇编语言中条件跳转指令有很多种,如 je2 表示当比较结果为 a=b 时跳转到主存地址为2的位置。若采用无条件转移指令 jmp2 ,就不会管PSW的各种标志位,使PC的值为主存地址2。

具体想要学习的话,可以看这篇博客:http://t.csdnimg.cn/qN79z

(9)基址+变址复合寻址

在上述例子中,默认程序从主存地址为0的地址往后存放,因此,当IX为2时,则能定位到a[2]地址单元,也就是基址7+变址2=9主存地址

但若此程序从主存地址为100的地址开始存放,那么执行"ACC加法"时,就不能只用到变址寻址,而是需要基址寻址+变址寻址得到最终有效地址。

基址寻址:EA=(BR)+A

变址寻址:EA=(IX)+A

先基址后变址寻址:EA=((BR)+A)+(IX),即先把形式地址A+BR,使其指向a[0],接下来进行变址寻址,即+(IX),就能得到最终的有效主存地址109

注:实际应用中往往需要多种寻址方式复合使用(可理解为复合函数,因为每一种寻址方式都是要将形式地址A映射为有效地址EA,只是不同寻址方式映射规则不同,多种寻址方式复合,就是将不同映射规则结合起来,相当于数学中的复合函数)

(10)相对寻址

相对寻址把程序计数器PC的内容加上指令格式中的形式地址A而形成操作数的有效地址,即

EA=(PC)+A,其中A是相对于PC所指地址(下一条指令地址)的位移量,可正可负,补码表示。

如图所示,CPU从主存地址为1000的位置中取出指令,每当CPU取出一条指令,都会使PC指向下一条指令的存放地址。 

若当前指令字长=2B,则PC+2

若当前指令字长=4B,则PC+4

因此取出当前指令后,PC可能为1002或1004,假设当前(PC)=1002

若采用相对寻址,则EA=(PC)+A---->EA=1002+A,所以A是相对于下一条指令的位移量

相对地址的作用:

如下图所示,“条件跳转”使用的是直接寻址的方式

若该for循环被挪动了位置,再按照之前直接寻址的方式进行解析,即跳转到主存地址为2的位置,则会出现错误。

所以引入相对寻址,若当前执行的指令为“条件跳转”,那么PC的值会自动+1,指向M+4主存地址,为了该for循环正常工作,可以让PC的值指向主存地址为M的位置,即M+4-4。

由于跳转指令本质是在修改PC的值,那么会把相对寻址得到的有效地址赋给PC,让PC重新指向主存地址为M的位置。

所以无论for循环被挪到哪一个位置,都不需要修改跳转指令的地址码,采用相对寻址,就能得到正确的结果。

优点:这段代码在程序内浮动时不用更改跳转指令的地址码

注:对于“ACC加法”,若挪动这一for循环的位置,数组的起始地址可能不是主存地址为7的位置,对于程序员而言,若挪动for循环的位置,还需要修改地址参数,显然是很麻烦的

可以采用“分段”方式,就是将程序分为程序段,数据段,用数据段专门存放数据。例如,将数组a存放在数据段的起始地址为7的位置,那么a存放的地址在段中的相对位置不变,也就是形式地址A不需要改变。如下图所示,相对地址7就不需要修改了。

优点:操作数的地址不是固定的,它随着PC值的变化而变化,并且与指令地址之间总是相差一个固定值,因此便于程序浮动(一段代码在程序内部的浮动)。

相对寻址广泛应用于转移指令。

注:

在基址寻址中说的程序浮动,指的是整段程序在内存中的浮动,而相对寻址说的程序浮动指的是一段代码在程序内部的浮动

(11)堆栈寻址

操作数存放在堆栈中,隐含使用堆栈指针(SP)作为操作数地址。

硬堆栈

堆栈是存储器(或专用寄存器组)中一块特定的按"后进先出(LIFO)"原则管理的存储区,该存储区中被读/写单元的地址是用一个特定的寄存器给出的,该寄存器称为堆栈指针(SP)。

如图所示,假设寄存器已被存满,SP指向栈顶元素(R0),由于只有4个寄存器,则用2个bit位就可以表示所有寄存器的编号(2^2=4)

假设需要使用堆栈的两个栈顶元素完成一次加法操作,如图所示,加数和被加数需要放到ACC与X这两个寄存器中,通过ALU的计算,将结果输出到另一个寄存器中

记栈顶单元为Msp,首先POP ACC,即弹出栈顶元素,放到ACC寄存器中,那么SP指针+1,指向次栈顶元素

接下来POP X,再将栈顶元素弹出,放到X寄存器中,SP指针继续+1

接下来将加法的结果放到寄存器Y中,即ADD Y        (ACC)+(X)-->Y

最后PUSH Y,将运算结果压回栈顶。首先SP=SP-1,然后再将Y的值放到SP指向的寄存器中 

可以看到POP ACC和PUSH Y,这两个指令所存放的位置是被隐含在SP中的

出栈时,首先弹出SP指向的元素,接着(SP)+1--->SP

入栈时,首先(SP)-1--->SP,接着再将想要存的元素存到SP所指的寄存器中。

总结:

栈顶在小地址方向

栈顶在大地址方向

•软堆栈

以上堆栈寻址的实现是采用专门的寄存器的,可以将其称为硬堆栈,还有一种为软堆栈,即从主存中划分一片区域作为堆栈

采用硬堆栈与软堆栈的区别:

① 若采用软堆栈,弹出栈顶元素或压入一个元素就需要进行访存,而采用硬堆栈,由于堆栈元素都存放在寄存器中,无论弹出栈顶元素或压入一个元素都不需要进行访存使用硬堆栈,CPU运行速度会更快。

注:这里指的是"指令执行期间",硬堆栈不需要访存,而软堆栈需要访存,但是取指令的时候都是需要访问1次内存的。对于双目运算需要访问4次内存:取指令,取源数1,取源数2,存结果。

② 但是由于寄存器较贵,所以硬堆栈成本更高,而软堆栈成本更低。

实际系统中,通常会使用软堆栈,函数调用时保存的当前函数的相关信息,都会被保存在程序对应的软堆栈中。

总结:

各寻址方式的使用情况:

立即寻址:操作数获取便捷,通常用于给寄存器赋初值。

直接寻址:相对于立即寻址,缩短了指令长度。

间接寻址:扩大了寻址范围,便于编制程序,易于完成子程序返回。

寄存器寻址的指令字较短,指令执行速度较快。

寄存器间接寻址扩大了寻址范围。
基址寻址扩大了操作数寻址范围,适用于多道程序设计,常用于为程序或数据分配存储空间。

变址寻址主要用于处理数组问题,适合编制循环程序。

相对寻址用于控制程序的执行顺序、转移等。
基址寻址和变址寻址的区别:两种方式有效地址的形成都是寄存器内容+偏移地址,但是在基址寻址中,程序员操作的是偏移地址,基址寄存器的内容由操作系统控制,在执行过程中是动态调整的;而在变址寻址中,程序员操作的是变址寄存器,偏移地址是固定不变的。即:

基址寻址:(BR)+A

BR基址寄存器的内容由操作系统控制,程序员可操作偏移地址A。

变址寻址:(IX)+A

偏移地址A不变,程序员可操作的是变址寄存器IX。

8.CISC和RISC

CISC和RISC是指令系统的两种设计方向:

(1)CISC(Complex instruction Set Computer)

一条指令完成一个复杂的基本功能。例如,x86架构,主要用于笔记本,台式机等。

但随着指令越来越复杂,出现了80-20规律:典型程序中80%的语句仅仅使用处理机中 20% 的指令

比如设计一套能实现整数、矩阵加/减/乘运算的指令集:

CISC的思路:除了提供整数的加减指令除之外,还提供矩阵的加法指令、矩阵的减法指令、矩阵的乘法指令,并且一条指令由一个专门的电路完成。而有的复杂指令用纯硬件实现很困难,所以采用“存储程序’的设计思想,由一个比较通用的电路配合存储部件完成一条指令。例如设置加、减、乘电路,并且由这几个电路一起完成矩阵乘法指令。

总结:

CISC可以提供很多复杂的指令,对于一些特别复杂的指令,无法使用某一硬件电路实现,就会采用微程序实现。

(2)RISC(Reduced instruction Set Computer)

一条指令完成一个基本“动作”;多条指令组合完成一个复杂的基本功能。例如,ARM架构,主要用于手机,平板等。

比如设计一套能实现整数、矩阵加/减/乘运算的指令集:

RISC的思想:只提供整数的加减乘指令

一条指令一个电路,电路设计相对简单,功耗更低

注意:RISC的主要目标是减少指令数,因此会选取使用频率最高的一些简单指令,以及很有用但不复杂的指令,但是如果RISC想实现一些复杂的功能,只能多个简单指令的组合实现。

RISC中指令相对简单,功能单一,可以较方便地设计出定长指令结构,指令执行时间相差不大,所以适用于"并行","流水线"。

总结:

这里特别说明:

① 对于CISC而言,可访存指令是不加限制的,而RISC中,可访存指令只有Load(某数据从主存中取出)/Store(某数据放入主存)指令,若某程序的乘法指令可以访存,那么一定是CISC

在CISC中,乘法指令会将需要相乘的数从主存中取出,放到相应的寄存器中进行乘法操作,不会过多占用寄存器

在RISC中,需要用Load指令访存,将数据从主存取出,放到寄存器中,再用乘法指令对两个寄存器的值相乘,这样就会占用较多寄存器。也就是只有取数/存数指令访问存储器,其余指令的操作均在寄存器之间进行,所以RISC的一大特点就是CPU配备很多通用寄存器。

② CISC中,绝大多数为微程序控制。RISC中,绝大多数为组合逻辑控制。以硬布线逻辑为主,不用或少用微程序控制。

③ CISC中,由于各指令执行时间相差较大,所以指令流水线会比较困难,但是也可以通过一定方式实现。RISC中,各指令执行时间绝大多数可以在一个周期内完成,所以较容易实现指令流水线。流水线会使CPU效率提高很多,所以RISC必须实现指令流水线。

④ 从指令系统兼容性看,CISC大多能实现软件兼容,即高档机包含了低档机的全部指令,并可加以扩充。但RISC简化了指令系统,指令条数少,格式也不同于老机器,因此大多数 RISC 机不能与老机器兼容。由于 RISC 具有更强的实用性,因此应该是未来处理器的发展方向。但事实上,当今时代 Intel 几乎一统江湖,且早期很多软件都是根据 CISC设计的,单纯的 RISC 将无法兼容。此外,现代 CISC结构的 CPU已经融合了很多 RISC的成分,其性能差距已经越来越小。CISC可以提供更多的功能,这是程序设计所需要的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值