计算机体系结构(1):指令集

对应《计算机体系结构:量化研究方法》(第六版)附录A内容。


指令集设计是计算机体系结构设计中重要的一环, 指令集作为计算机 软件硬件的接口,会对软件编码和程序执行效率等一系列问题产生影响。

指令集架构分类

根据操作数(operand)在处理器内部存储位置的不同,可以将指令集架构分为以下几类:栈架构(stack architecture)累加器架构(accumulator architecture)通用寄存器架构(general-purpose register architecture)。而通用寄存器架构,根据操作数的来源,又分为两类:寄存器-存储(register-memory)寄存器-寄存器(register-register / load-store)。如下图所示,在栈架构中,操作数存储在堆栈中;在累加器架构中,其中一个操作数存储在累加器中;在通用寄存器架构中,寄存器-存储架构,操作数可以来自于寄存器,也可以来自于存储器,而寄存器-寄存器架构,操作数只能来自于寄存器,如果操作数开始位于存储器中,需要使用额外的指令(load指令)将操作数装载到寄存器,并且在计算完成后,需要将结果用存储指令(store指令)保存到存储器。
在这里插入图片描述
如下表所示,每一类指令集架构对应的程序。现在需要完成代码C=A+B,四种不同的指令架构对应的程序也不相同,在栈架构和累加器架构中,有的操作数是隐式(implicitly)的表示,而在通用寄存器架构中,所有操作数都需要显式(explicitly)表示。
在这里插入图片描述
初期计算机一般采用栈架构和累加器架构,1980年后计算机一般都采用寄存器-寄存器(load-store)这种通用寄存器架构。通用寄存器架构的优点主要体现在寄存器的速度远远快于存储器的速度,并且对于编译器来说,寄存器更为高效
关于通用寄存器架构,还可以依据操作数的数量进行划分。下面给出常用指令集的操作数个数,以及这些操作数中内存地址的数量。三个操作数的指令集,其中两个操作数为源操作数,一个操作数为目的操作数,两个操作数的指令集,两个操作数都为源操作数,并且其中一个操作数也要作为目的操作数。
在这里插入图片描述
下面给出寄存器-寄存器架构、寄存器-存储架构,这两种通用寄存器架构指令集的优势和缺陷。

  • 寄存器-寄存器架构(最大操作数:3,操作数中的存储地址:0)
    • 优势:简单,且固定长度的指令编址。指令集中每条指令的执行时间固定。
    • 缺陷:在编写程序时,相比于操作数中包括存储地址的指令集架构,需要更多的指令。更多的指令会对指令Cache造成影响。
  • 寄存器-存储架构(最大操作数:2,操作数种的存储地址:1)
    • 优势:存储器种数据的访问不需要额外的指令。
    • 缺陷:由于操作数种有存储地址,所以操作数的长度不固定。由于一条指令种可能存在寄存器和存储地址,所以会限制寄存器的数量。每条指令的执行时间不固定。

存储寻址

首先需要明确存储器中每个存储单元中的数据如何解释。现在计算机有两种解释方法。

  • 大端(big endian):数据的低位存储在高地址。
  • 小端(little endian):数据的低位存储在低地址。

对于按字节(byte)编址的存储器,需要存储的十六进制数据为0x12345678大端模式下,该数据在存储器中的应该为(地址由低到高)12345678小端模式下,该数据在存储器中的应该为(地址由低到高)78563412
另外,数据在存储器中可以按对齐方式(aligned)非对齐方式(misaligned)存储,其中以对齐方式存储的数据在数据存取时的速度要高于以非对齐方式存储的数据。
下面介绍存储的寻址模式,为了支持不同应用场景下的寻址需求,下表给出了常用了寻址模式,及使用示例和相应解释。其中使用比较多的是位移寻址(displacement)立即寻址(immediate)位移寻址关键是确定指令中位移量所占的长度,立即寻址关键是确定指令中立即数所占的长度。
在这里插入图片描述

控制指令

相较于算术运算等指令,在指令集架构中控制指令需要考虑更多的问题。
首先是控制指令的寻址模式,即如何确定下一条指令的地址。现在比较常用的有:

  • PC相关(PC-relative),即程序计数器(Program Counter,PC)相关,即在当前的PC上增加一个位移量,表示下一条指令的地址。该模式的优点是编写出来的代码运行时和具体的装载位置无关(position independence)
  • 寄存器间接跳转(register indirect jump),即在寄存器中存储跳转地址。该模式可以很好的解决需要在运行时确定跳转地址的情况,例如,虚函数、函数指针和动态库等。

然后,需要考虑分支(branch)指令跳转选择,即如何判断分支指令是否需要跳转。现在常用的有:

  • 条件代码(Condition Code,CC):比较状态寄存器的某一位决定是否跳转,状态寄存器的位可以通过ALU操作进行设置。该方法需要额外的状态寄存器,且分支是否跳转,需要根据程序流确定,因为程序的信息是会依据程序流顺序传递到分支指令。
  • 条件寄存器(Condition register):比较任意寄存器的值决定是否跳转。
  • 比较分支(Compare and branch)比较对象为分支指令的一部分,在指令中明确了需要比较的对象。该方法只需要一条指令就可以实现分支操作。

最后,需要考虑过程调用,过程调用指令本质上也是一种跳转指令。由于调用过程(caller procedure)被调用过程(called procedure)可能需要使用相同的寄存器,为保证被调用过程返回后,调用过程的程序可以正常执行,即调用过程中寄存器状态恢复到调用前,需要在调用过程或被调用过程中保存相应寄存器寄存器,其中,调用过程需要保存的寄存器,称为调用方保存(caller saving)寄存器,被调用过程需要保存的寄存器,称为被调用方保存(callee saving)寄存器。不同指令集架构这两类寄存器并不相同,具体可以查看指令集架构的调用规则(calling convention)的相关内容。

指令编码

指令集架构中每条指令,不仅需要包含每条指令需要执行的操作,还需要说明操作数的获取方式,所以指令编码中需要重点考虑操作数寻址模式的编码
对于指令的编码,需要综合考虑指令集架构中寻址模式的数量操作码与寻址模式的关联度。现在主要使用的有三种不同的指令编码方式:

  • 可变(variable)编码,每条指令的长度并不固定,允许所有的寻址模式,每个操作数前会有寻址说明符(address specifier)说明相应的寻址模式。可变编码指令集对应的程序规模较小,但是每条指令的译码会更加复杂。
  • 固定(fixed)编码,每条指令的长度固定,允许少量的寻址模式寻址模式和操作码绑定。固定编码指令集每条指令的译码相对简单,但是程序的规模较大。
  • 混合(hybrid)编码,上述两种编码方式的折中,指令集中有多种长度的指令,例如,指令集可以指令32bit和16bit长度的指令。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值