lec13-指令系统
1. overview
2. 指令表示
2.1. 指令的要素
- 操作码:指定将要完成的操作(opcode)
- 源操作数引用:操作可能涉及一个或者多个源操作数,这是操作的输入
- 结果操作数引用
- 下一条指令引用:告诉处理器下一个指令要去哪里取出
2.2. 指令表示
指令格式:二进制串划分成几个字段,包括操作码,操作数;
- 大多数的指令集使用了不止一种指令格式
这带来一个问题:是否存在两种解读方式?- 解决方法:避免二义性,使得只有一种有意义的解读
2.3. 操作码
- 不同的计算机上的操作码的数目变动比较大
- 所有计算机上都会存在相同的常用操作类型
- 数据传送(load, store…)
- 算术运算(add, sub…)
- 逻辑运算(and, or…)
- 转换( ? )
- 输入/输出(in, out)
- 系统控制(ecall, ebreak…)
- 控制转移(jal, branch…)
2.3.1. 数据传送
下面是数据传送指令应该包含的信息(或者说不同的数据传送指令之间的不同点)
- 指明源操作数和目标操作数的位置
- 指明将要传送的数据长度
- 指明每个操作数的寻址方式
2.3.2. 算术运算
- 一条算术运算的执行会涉及到数据传送操作:需要准备输入,并传送输出
- 可以说,计算得到的结果只有存放到一个地方才是有意义的
2.3.3. 逻辑运算
- 位操作(and, or, not, x-or… )
- 移位和旋转(shift, rotate…)
- compare, set…
2.3.4. 输入/输出
- 各种输入/输出方法仅有少数输入/输出指令实现,具体操作由参数、代码或者命令字指定
2.3.5. 控制转移
-
- 分支指令
- 跳步指令(JMP?)
- 过程调用指令
-
实际上,分支/跳转指令,将要执行的下一条指令的地址作为它的操作数之一;
-
跳步指令:包含一个隐含地址,这个隐含地址等于下一指令地址加上该指令长度之和
-
过程调用指令:
- 涉及到从目前的位置转移到某个过程的调用指令,以及由过程返回到调用发生位置的返回指令
- 一些方法,当然为了满足递归调用等情景,最终是栈调用
-
使用寄存器
-
存储在过程开始处
-
使用栈来保存(现场)
-
2.4. 操作数
- 常见类型:
- 地址
- 数值
- 字符
- 逻辑数据
2.4.1. 地址
- 一个指令会需要若干个地址引用(可能是显式的,也可能是隐式的)
- 一般是2个源操作数,1个目的操作数,下一指令地址
- 指令中的地址数量与指令条数之间:
- 每条指令中的地址数量越少
- 指令的长度越短,不需要复杂的CPU(因为可变部分变少,不需要复杂的硬件设计)
- 程序的总的指令条数更多,执行时间更长
- 一些运算,可以使用通用寄存器; 但是有些计算只使用特定的寄存器进行完成
- 每条指令中的地址数量越少
- ADD Y A B
ADD Y B
ADD B
ADD 0
2.4.2. 数值
- 计算集存储的数据是受限制的
- k k k 位数长度的二进制编码,最多可以表示 2 k 2^k 2k不同的数字,这是一定的
2.4.3. 字符
- IRA 国际参考字母表 / ASCII 美国信息交换标准码,每个字符被表示成唯一的7位二进制串
- EBCDIC,扩展的二进制编码的十进制交换码:8位编码
- 统一码(Unicode):16/32位
2.4.4. 逻辑数据
- 1为 true, 0为 false
2.4.5. 大端序 小端序
- 人类的习惯来说,类似于大端序,按顺序读取数据的过程也是数据从小地址到大地址,也是数据组织的顺序
2.5. 操作数引用
- 操作数的实际值
- 操作数的地址,可能存放在
- 寄存器
- 主存/虚拟内存
- …
有多种的寻址方式
2.5.1. 一些记号
- A:指令中地址字段的内容
- R:指向寄存器的指令地址字段内容
- EA:被访问位置的实际(有效)地址
- (X):存储器位置 X 或者 寄存器 X 的内容(类似与解引用的效果)
2.5.2. 立即寻址(可以记为立即数寻址)
- 算法:操作数 = A
- 优点:不要求额外的存储器访问
- 缺点:数的大小收到地址字段的长度限制
2.5.3. 直接寻址
- 算法:EA = A
- 优点:只需要一次存储器访问
- 缺点:有限的地址空间(因为地址收到A长度的限制)
2.5.4. 间接寻址
- 算法:EA = (A)
- 优点:扩大了地址空间
- 缺点:取操作数需要2次的访问存储器
2.5.5. 寄存器寻址
- 算法:EA = R, 也就是 操作数 = (R)
- 优点:指令中只需要一个很小的地址字段,而且不需要存储器访问
- 缺点:地址空间很有限
2.5.6. 寄存器间接寻址
- 算法:EA = (R)
- 优点:扩大了地址空间,比间接寻址少了1次存储器访问
- 缺点:相对于寄存器寻址,多了一次存储器寻址
2.5.7. 偏移寻址
-
包括了:
相对寻址,基址寄存器寻址,变址 -
整体算法:EA = (R) + A
-
偏移寻址本身要求:指令有两个地址字段,至少其中一个是显式的
- 相对寻址:
- 隐含的寄存器是程序计数器(PC)
- 算法:EA = (PC) + A
- 优点:利用了程序局部性原理,节省指令中地址的位数
- 基址寄存器寻址:
- 方式:被引用的寄存器含有一个地址(也就是基址)
- 算法:EA = (B) + A
- 用法:虚拟内存空间中的程序重定位
- 变址寻址:
- 方式:指令地址字段存下的是存储器地址,寄存器含有一个偏移量
- 算法:EA = A + (R)
- 用法:为完成重复操作,提供一种高效机制(循环操作等等)
2.5.8. 栈寻址
- 方式:栈指针保存在寄存器中,对寄存器中栈位置的访问实际上也是一种寄存器间接寻址方式
2.5.9. 栈
- 栈的操作:push, pop, 一元操作,二元操作
- 栈的应用:后缀表达式,容易完成运算
3. 指令格式
3.1. 指令格式的设计原则
- 指令尽量短
- 减少程序占用空间
- 有足够的操作码位数
- 为了操作类型增加预留位数
- 操作码的编码要有唯一的解释方法
- 指令长度是字节的整数倍
- 方便取指令等等
- 合理选择地址字段的个数
- 涉及到指令长度和规整性,是空间和时间开销权衡的结果
- 指令尽量规整
- 这样可以简化硬件的实现(布线可以简单化)
3.2.1. 指令长度
- 权衡:发生在强有力的指令清单和节省空间之间进行
- 编程人员希望:更多的操作码(多种操作),更多的操作数,更多的寻址方式,更大的地址范围
- 指令长度变短:有利于节省存储空间,减少数据传送时间
- 指令长度应该是等于存储器的传送长度(数据总线宽度),或者是整数倍
3.2.2. 位分配给字段
- 对于给定的指令长度,在操作码数目和寻址能力之间存在着权衡考虑
- 使用变长的操作码:
- 有一个最小操作码长度,对于某些操作码就可以获得更多的位数(RISC v32中就有体现)
- 使用寻址位的考虑因素:
3.3.3. 变长指令
- 提供不同长度的各种指令格式
- 优点
- 可以提供大的操作码清单,操作码具有不同的长度
- 寻址方式更加灵活*(?)*
- 缺点:
- 硬件非常复杂
3.3.4. 指令集设计
- 指令集是软件和硬件的中间地带
- 指令集定义了处理器应该实现的功能(对硬件影响大)
- 指令集给出程序员操作处理器的方式(对软件的影响)
- 设计的一些原则
- 完整性
- 兼容性
- 均匀性
- 可以扩展性
- 设计的基本问题