指令系统

0x00.机器指令

计算机就是连续执行每一条机器语句而实现全自动工作的。人们习惯把每一条机器语言的语句称为机器指令,而又将全部机器指令的集合称为机器的指令系统。

指令的一般格式

操作码字段 地址码字段

指令的长度是指一条指令中所包含的二进制代码的位数,它取决于操作码字段的长度、操作数地址的个数及长度,指令长度与机器字长没有固定的关系。

操作码

操作码用来指明该指令所要完成的操作,如加法、减法、传送、移位、转移等。通常,其位数反映了机器的操作种类,也即机器允许的指令条数,如操作码为7位,则该机器最多包含2^7=128条指令。

操作码的长度可以是固定的(一般用于大中型计算机和超级小型计算机),也可以是不固定的(一般用于字长较短的微型计算机)

对于操作码长度不固定的指令,其操作码分散在指令字的不同字段中。因为不固定,所以会增加指令译码和分析的难度,使控制器的设计复杂,通常采用扩展操作码技术,使操作码的长度随着地址数的减少而增加,不同地址数的指令可以具有不同长度的操作码

资源路径有问题

如何理解“条地址指令”?

例如15条3地址指令,意思就是说最多有 15个运算符号(指令)可以用于作用3个地址的数据。

当操作码取4位时,三地址指令最多为15条;操作码为8位时,二地址指令最多为15条;操作码取12位时,一地址指令最多为15条;操作码为16位时,零地址指令为16条。共61条

地址码

地址码用来指出该指令的源操作数的地址(一个或两个)、结果的地址以及下一条指令的地址(这里的地址可以是主存的地址,也可以是寄存器的地址,甚至可以是I/O设备的地址,下面以访问主存为例

  • 四地址指令
    OP A1 A2 A3 A4
    其中,OP为操作码,A1为第一操作数地址;A2为第二操作数地址;A3为结果地址;A4为下一条指令的地址;

实现操作:(A1)OP(A2)->A3

完成一条四地址指令,共需访问四次存储器。

因为程序中大多数指令是按顺序执行的,而程序计数器PC((program counter))既能存放当前欲执行指令的地址,又有计数功能,因此它能自动形成下一条指令的地址,因此我们完全可以利用好PC来节省第四个地址字段

  • 三地址指令
    OP A1 A2 A3

实现操作:(A1)OP(A2)->A3

完成一条三地址指令,共需访问四次存储器,后续指令的地址隐含在程序计数器PC中。

机器在运行过程中,没有必要将每次运算结果都存入主存,中间结果可以暂时存放在CPU的寄存器(如ACC)中,这样又可以省去一个地址字段A3,从而得出二地址指令

  • 二地址指令
    OP A1 A2

实现操作:(A1)OP(A2)->A1,即A1字段既代表源操作地址数的地址,又代表存放本次运算结果的地址。

完成一条二地址指令,仍然需访问四次存储器,后续指令的地址隐含在程序计数器PC中。如果使用(A1)OP(A2)->ACC,此时,它完成一条指令只需3次访存,它的含义是中间结果暂存于累加器ACC中。

如果将一个操作数的地址隐含在运算器的ACC中,则指令字中只需给出一个地址码,构成一地址指令

  • 一地址指令
    OP A1

它可完成(ACC)OP(A1)->ACC的操作,ACC既存放参与运算的操作数,又存放运算的中间结果。这样完成一条指令只需要2次访存。

你以为结束了?no、no、no,在指令系统中,还有一种指令可以不设地址字段,即所谓零地址指令。

  • 零地址指令
    OP A1

零地址指令在指令字中无地址码,例如,空操作(NOP)、停机(HLT)这类指令只有操作码。
而子程序返回(RET)、中断操作(IRET)这类指令没有地址码,其操作数的地址隐含在堆栈指针SP中。

上述可见,用一些硬件资源(如PC、ACC)承担指令字中需指明的地址码,可在不改变指令字长的前提下,扩大指令操作数的直接寻址范围,还可缩短指令字长、减少访存次数。

指令字长

指令字长取决于操作码的长度、操作数地址的长度和操作数地址的个数,不同机器的指令字长是不相同的。


0x01.操作数类型和操作类型

操作数类型

机器中常见的操作数类型有地址、数字、字符、逻辑数据等。

  • 地址
    地址实际上也可看做是一种数据,在许多情况下要计算操作数的地址,这时,地址可以被认为是一种无符号整数。
  • 数字
    计算机中常见的数字有定点数、浮点数和十进制数。
  • 字符
    在应用计算机中,文本或者字符串也是常见的数据类型。由于计算机在处理信息的过程中不能以简单的字符形式存储和传送,因此普遍采用ASCII码,它是一种很重要的字符编码。当然也还有其他的字符编码,如8位EBCDIC码,又称BCD交换码。
  • 逻辑数据
    计算机除了作算术运算外,有时还需作逻辑运算,此时n个0和1的组合不是算术运算,而是被看做逻辑运算。

数据在存储器中的存放方式

通常计算机中的数据存放方式在存储器或寄存器中,而寄存器的位数便可反映机器字长,一般机器字长可取字节的1、2、4、8倍,这样便于字符处理。

操作类型

不同的机器,操作类型也是不同的,但几乎所有的机器都有下面几类通用的操作

  • 数据传送
    数据传送包括寄存器与寄存器、寄存器与存储单元、存储单元与存储单元之间的传送。例如从源到目的之间的传送、对存储器读(LOAD)和写(STORE)、交换源和目的的内容、置1、清零、进栈、出栈等。
  • 算术逻辑操作
    这类操作可实现算术运算(加、减、乘、除、增1、减1、取负数即求补)和逻辑运算(与、或、非、异或)
  • 移位
    移位可以分为算术移位、逻辑移位和循环移位三种。算术移位和逻辑移位分别可实现对有符号数和无符号数乘以/除以2的操作。
  • 转移
    在多数情况下,计算机是按照顺序执行程序的每条指令的,但有时需要改变这种顺序,此刻可以采用转移类指令来完成。转移指令按其转移特征又分为:无条件转移、条件转移、跳转、过程调用与返回、陷阱(Trap)等几种
  1. 无条件转移

    无条件转移不受任何条件约束,可直接把程序转移到下一条需执行的指令的地址。例如“JMP X”,其功能是将指令地址无条件转至 X
  2. 条件转移

    条件转移是根据当前指令的执行结果来决定是否需要转移。若条件满足,则执行;不满足,则继续按顺序执行。一般机器都能提供一些条件码,这些条件码是某些操作的结果。例如:零标志位(Z),结果为0,Z=1;负标志位(N),结果为负,N=1;溢出标志位(V),结果有溢出,V=1;进位标志位(C),最高位有进位,C=1;奇偶标志位(P),结果为偶数,P=1等。即满足条件,标志位就置1。
    还有一种条件转移指令,SKP(Sjip),它暗示其下一条指令将被跳过,从而隐含了转移地址是SKP后的第二条指令,即符合SKP后面的条件的话,跳过SKP的下一条指令,直接到下一条的下一条执行。
  3. 调用与返回
    在编写程序时,有些具有特定功能的程序段会被反复调用。为了避免重复编写,可将这些程序段设定为独立子程序(也就是封装成函数来提高代码复用率),当需要执行某子程序时,只需用子程序调用指令即可。此外,计算机系统还提供了通用子程序,如申请资源、读写文件、控制外设等。需要时均可由用户直接调用,不必重新编写。
    通常条用指令包括过程调用、系统调用、子程序调用,它可实现从一个程序转移到另一个程序的操作。
    调用指令(CALL)一般与返回指令(RETURN)配合使用。CALL用于从当前的程序位置转至子程序的入口;RETURN用于子程序执行完后重新返回到原程序的断点。

需要注意一下几点:

  • 子程序可在多处被调用
  • 子程序调用可出现在子程序中,即允许子程序嵌套
  • 每个CALL指令都对应一条RETURN指令

由于可以在多处调用子程序,因此,CPU必须记住返回地址,使子程序能准确返回。返回地址可存放>在以下三处:

  1. 寄存器内。机器内设有专用寄存器,专门用于存放返回地址
  2. 子程序的入口地址内
  3. 栈顶内。现代计算机都设有堆栈,执行RETURN指令后,便可自动从栈顶内取出应返回的地址

这些东西建议在Linux操作系统上利用gcc工具编译C/C++语言来体验一下,看看汇编语言。

生成预编译文件:
g++ -E intdex.cpp -o index.i

生成汇编文件:
g++ -S intdex.i -o index.s

  1. 陷阱(Trap)与陷阱指令

    陷阱其实是一种意外事故的中断。例如,计算机在运行中,可能会出现电源电压不稳定、存储器校验出错、输入输出设备故障、用户使用未被定义的指令、除数出现了0、运算结果溢出以及特权指令等种种意外事件,致使计算机不能正常工作。此刻必须及时采取措施,否则将影响整个系统的正常运行。因此,一旦出现意外故障,计算机就会发出陷阱信号,暂停当前程序的执行,转入故障处理程序进行相应的故障处理

    计算机的陷阱指令一般不提供给用户直接使用,而作为隐指令(即指令系统不提供的指令),在出现意外故障时,由CPU自动产生运行。也有的机器设置供用户使用的陷阱指令或“访管”指令,利用它完成系统调用和程序请求。
  • 输入输出
    对于I/O单独编址的计算机而言,通常设有输入输出指令,它完成从外设中的寄存器读入一个数据到CPU的寄存器内,或将数据从CPU的寄存器输出至某外设的寄存器。
  • 其他
    其他还有等待指令、停机指令、空操作指令、开中断指令、关中断指令等。

0x02.寻址方式

寻址方式是指确定本条指令的数据地址以及下一条将要执行的指令地址的方法。

寻址方式分为指令寻址数据寻址两大类

指令寻址

指令寻址比较简单,它分为顺序寻址和跳跃寻址两大类。

顺序寻址

顺序寻址可通过程序计数器PC加1,自动形成下一条指令的地址;

跳跃寻址

跳跃寻址通过转移类指令实现。

例如操作类型中的无条件转移的转移指令”JMP X”,直接跳转到X的地址

数据寻址

数据寻址的方式种类很多,在指令字中必须设一字段来指明属于哪一种寻址方式。指令的地址码字段通常都不代表数的真实地址,把它成为形式地址,记作A。操作数的真实地址称为有效地址,记作EA,它是由寻址方式和形式地址共同来确定的。

一种一地址指令的格式如下:

操作码 寻址特征 形式地址A

有效地址=寻址特征+形式地址A

下面我们来介绍几种数据寻址方式,为了便于研究和分析各类寻址方式,假设指令字长、存储字长、机器字长均相同。

立即寻址

立即寻址的特点是操作数本身设在指令字内,即形式地址A不是操作数的地址,而是操作数本身,又称之为立即数。

即该放地址的地方直接放上数据

操作码 # A
#:立即寻址特征
A:立即数

优点:只要取出指令,立即获得操作数,执行阶段不必访问存储器

缺点:立即数的位数限制了这类指令所能表述的立即数的范围

直接寻址

直接寻址的特点是,指令字中的形式地址A就是操作数的真实地址EA,即 EA=A

操作码     A
A-->主存中的地址-->操作数

优点:寻找操作数很简单,在指令执行阶段只需要对主存访问一次。

缺点:A的位数限制了操作数的寻址范围,而且必须修改A的值,才能修改操作数的地址。

隐含寻址

隐含地址是指指令字中不明显地给出操作数的地址,其操作数的地址隐含在操作码或某个寄存器中。例如一地址格式的加法指令只给出一个操作数的地址,另一个操作数隐含在累加器ACC中,这样累加器ACC成了另外一个数的地址。

操作码     A
A-->主存中的地址-->操作数-->ALU-->暂存-->ACC-->ALU

由于隐含寻址在指令字长中少了一个地址,因此这种寻址方式的指令有利于缩短指令字长。

间接寻址

倘若指令字中的形式地址不直接指出操作数的地址,而是指出操作数有效地址所在的存储单元地址,也就是说,有效地址是由形式地址间接提供的,即为间接寻址,即EA=(A)

  • 可以利用C++的知识这么想:对于直接寻址A就是操作数的地址,所以*A就是操作数本身。对于间接寻址(以一次间接寻址为例),A是一个地址, 且 *A得到的仍然是一个地址,只有 * ( *A )才是最后的操作数。

    资源路径有问题

优点:扩大了寻址范围(一般A的位数通常小于指令字长,而存储字长可与指令字长想等,所以一般A的可表示范围是小于存储字长的可表示范围,所以间接寻址,存储字长用来存地址的话,可以有更大的范围)

缺点:指令的执行阶段需要访存两次或多次,造成过指令执行时间延长。

当多次间接寻址时,可用存储字的首位来标志间接寻址是否结束。当存储字首位为1,表明还需要继续访存寻址;当存储字首位为0,表明该存储字即为EA,故存储字首位不能作为EA的组成部分

寄存器寻址

在寄存器寻址的指令字中,地址码字段直接指出了寄存器的编号,即EA=R。其操作数在由R所指的寄存器中。由于操作数不在主存中,故寄存器寻址在指令执行阶段无须访存,减少了执行时间。由于地址字段只需指明寄存器编号(计算机中寄存器数有限),故指令字较短,节省了存储空间,因此寄存器寻址在计算机中得到广泛应用。

资源路径有问题

寄存器间接寻址

寄存器中的内容不是操作数,而是操作数所在主存单元的地址号,即有效地址EA=(R)。与寄存器寻址相比,指令的执行阶段还需访问主存。与间接寻址相比,因有效地址不是存放在存储单元中,而是存放在寄存器中,故称其为寄存器间接寻址,比间接寻址少访存一次。

资源路径有问题

基址寻址

基址寻址设有基址寄存器BR,其操作数的有效地址EA等于指令字中的形式地址与基址寄存器中的内容(称为基地址)相加,即:

EA=A+(BR)

因为基址寄存器的位数可以大于形式地址A的位数,所以基址寻址可以扩大操作数的寻址范围。

资源路径有问题

变址寻址

变址寻址与基址寻址极为相似。其有效地址EA等于指令字中的形式地址A与变址寄存器IX的内容相加之和,即:

EA=A+(IX)。

资源路径有问题

变址寻址与基址寻址的有效地址形成过程极为相似,但是由于二者的应用场合不同,因此从本质上讲他们还是有很大区别的。基址寻址主要用于为程序或数据分配存储空间,故基址寄存器的内容通常由操作系统或管理程序确定,在程序的执行过程中其值是不可变的,而指令字中的A是可变的。在变址寻址中,变址寄存器的内容是由用户设定的,在程序执行过程中其值可变,而指令字中的A是不可变的。变址寻址主要用于处理数组问题,在数组处理的过程中,可设定A为数组的首地址,不断改变变址寄存器IX的内容,便可很容易形成数组中任一数据的地址,特别适合编制循环程序。

相对寻址

相对寻址的有效地址是将程序计数器PC的内容(即当前指令的地址)与指令字中的形式地址A相加而成,即EA=(PC)+A。常被用于转移类指令

资源路径有问题

相对寻址最大的特点是转移地址不固定,它可随PC值的变化而变化,因此,无论程序在主存的哪段区域,都可正常运行,对于编写浮动程序特别有利。

堆栈寻址

堆栈寻址要求计算机中设有堆栈。堆栈既可用寄存器组(称为硬堆栈)来实现,也可以利用主存的一部分空间作为堆栈(称为软堆栈)。堆栈的运算方式为先进先出或先进后出两种,先进后出型堆栈只能从一个口进行读或写。以软堆栈为例,可用堆栈指针SP(Stack Point)指出栈顶地址,也可用CPU中一个或两个寄存器作为SP。操作数只能从栈顶地址指示的存储单元存或取。可见堆栈寻址也可视为一种隐含寻址,其操作数的地址总被隐含在SP中。堆栈指针就其本质也可视为寄存器间接寻址,因SP可视为寄存器,它存放着操作数的有效地址。

例:一条双字节直接寻址的子程序调用指令,其第一个字为操作码和寻址特征,第二个字为地址码>5000H。假设PC当前值为2000H,SP的内容为0100H,栈顶内容为2746H,存储器按字节编址,而且进>栈操作是先执行(SP)- x ->SP,后存入数据。

在CALL指令调用之前:PC=2000H,SP=0100H、栈顶内容为2746H。

CALL指令被执行后,由于存储器按字节编址,CALL指令共占4个字节,故程序断点2004H进栈,此时SP=(SP) - 2 = 00FEH,栈顶内容为2004H,PC被更新为子程序入口地址5000H。

子程序返回后,程序断点出栈,PC=2004H,SP被修改为0100H,栈顶内容为2746H。

欢迎请我喝奶茶(*゜ェ゜*)
---这篇文章到头了---感谢您的阅读-------------