指令系统
参考《计算机组成原理微课版》
视频https://www.bilibili.com/video/BV1Va4y177Dt
指令格式
计算机的运行需要指令,计算机的底层总是围绕“数据”和“状态”展开的。所以很直观地,指令可以改变计算机的状态,也可以控制进行数据处理运算。
指令由两部分构成,分别是操作码OP和地址码A。A可以有多个部分。
在三地址指令下各地址的意义是对 A 1 A_1 A1和 A 2 A_2 A2的内容进行OP操作,结果送入 A 3 A_3 A3进行存放
A 3 ← ( A 1 ) O P ( A 2 ) A_3 \leftarrow (A_1)OP(A_2) A3←(A1)OP(A2)
由于如果地址代表的是存储单元,则指令长度可能很大(毕竟对一个16K的地址范围寻址需要14位地址码,三个14位再加上操作码的位数得四五十位,很大),所以三个地址是寄存器比较多。
四地址指令,类似于三地址,但是 A 4 A_4 A4指出了下一条要执行的指令的地址。
双地址指令则将运算结果存入 A 1 A_1 A1中,而非其它地址
A 1 ← ( A 1 ) O P ( A 2 ) A_1 \leftarrow (A_1)OP(A_2) A1←(A1)OP(A2)
单地址指令有两种情况
- 默认了一个操作数的地址
- 单目运算
默认一个地址是另一个操作数根据约定可以去某个地方取到,例如累加器AC。这样有
A C ← ( A C ) O P ( A 1 ) AC \leftarrow (AC)OP(A_1) AC←(AC)OP(A1)
单目运算,比如说取反操作
零地址指令也有两种情况
- 默认了一个操作数
- 不需要操作数
不需要操作数比如说等待指令WAIT或者停机指令HALT等
像三地址指令这种没有指出下一个指令地址的指令,默认直接程序计数器(PC)+1得到下一个(即后续紧接着的指令)
关于变长操作码
定长指令意味着硬件实现简单,你只需要对一条指令(比如N位)取其前M位作为操作码,这样的规则在任何时候都可以得到遵守,这种定长操作码可以使译码和执行速度快。但是这种简单的代价是留给操作数的位数可能不够用。
变长操作码解决这样一个问题,在一条指令所占位数不变的情况下,如果地址部分占的位多,就让操作码占的少一点,反之亦然。即操作码的位数不固定。
那么相应的代价是译码和执行速度的减慢。想一想机器开始读取一些字节,它并不知道到底读取多少作为操作码,它不是被写死的固定M位(因此对应的硬件实现也更加复杂)。
我一看,这不就是前缀问题嘛(瞅两眼哈夫曼编码?)。举个例子,16位指令,地址是4位,显然在三地址指令时操作码是前四个数据位。
- 当是定长操作码时显然只能有 2 4 = 16 2^4=16 24=16条指令
- 整个指令集最多支持16条指令显然有点少,所以字长较大的机器适合定长操作码
- 变长操作码就比16条多,哪怕它的指令也是16位
但是计算机读取一串字节流后凭什么认为是变长操作码呢?这就有个扩展窗口的概念。
读前4个字节,如果是0000~1110则认为是三地址指令,如果是1111则再读四位,剩余没读的是两个地址,对应双地址指令。其中这个1111称为扩展窗口
这样三地址指令范围是0000 xxxx xxxx xxxx~1110 xxxx xxxx xxxx
,共15条
双地址指令的范围是1111 0000 xxxx xxxx~1111 1110 xxxx xxxx
,共15条
以上的xxxx都代表操作数地址
扩展窗口只是一个约定,不一定是1111,也未必只有一个
进一步地,读到1111 1111就再读四位,对应单地址指令。也有15条,即1111 1111 0000 xxxx~1111 1111 1110 xxxx
(其中xxxx是操作数的地址)
寻址方式
分为两类
- 操作码寻址
- 顺序寻址
- 跳跃寻址
- 操作数寻址
- 操作数在寄存器里的
- 操作数在主存里的
程序保存的是指令和数据,那么运行程序,就得不断地把事先加载到主存的指令和数据取出来
操作码寻址
顺序寻址类似于数组下标加一,这个PC+1的1是一条指令的字节长度,例如32位指令字长时就是PC+4
跳跃寻址是出现在分支或者转移时进行的操作
操作数寻址
- 立即寻址
- 直接寻址
- 寄存器寻址
- 间接寻址
- 寄存器间接寻址
- 相对寻址
- 变址寻址
- 基址寻址
- 堆栈寻址
- 其他寻址
操作数寻址分三部分,增加了寻址特征来指明具体的寻址方式。
|---OP---|---寻址特征---|---形式地址A---|
为什么叫形式地址呢,因为有可能是立即数,即读取字节作为一个数,不作为地址进行寻址。
基址寻址
|---OP---|---寻址特征---|---Ri---|---形式地址A---|
增加了一个 R i R_i Ri用于进行指明基址寄存器,该寄存器的值称为基地址,基地址加上形式地址A的值就是最终寻址的地址
- 可扩大寻址范围(基址寄存器的位数大于形式地址A的位数)
- 用户不必考虑自己的程序存于主存的哪一空间区域,故有利于多道程序设计
说明:基址寄存器是面向操作系统的,其内容由操作系统或管理程序确定。在程序执行过程中,基址寄存器的内容不变(作为基地址),形式地址可变(作为偏移量)。当采用通用寄存器作为基址寄存器时,可由用户决定哪个寄存器作为基址寄存器,但其内容仍由操作系统确定。
CISC与RISC
*适用频率:原文误,应为使用频率
指令流水线是避免了进行一个操作时,其他操作都等待的问题。比如说取指令时,译码相关工作区不干活,等取完指令得到结果才开始干活。
其中第四列就是流水线满运载的状态。
如果每个环节耗时
Δ
t
\Delta t
Δt,则这样的用时是
7
Δ
t
7\Delta t
7Δt,而不是每一轮四个项目执行完再执行下一轮这样的
16
Δ
t
16\Delta t
16Δt
精简指令格式规整,更适合指令流水线。