指令集架构
指令格式
区分特点:
- 每条指令所需的比特数
- 操作数存储位置(堆栈或寄存器)
- 每条指令包含的显示操作数(explicit operands)的个数
- 操作数的位置
- 操作类型
- 操作数的类型(地址、数值、字符)和大小
指令集设计决策
衡量指令集架构因素
- 程序所占空间大小
- 指令集的复杂程度
- 指令的长度
- 指令的总条数
设计指令集考虑
- 指令长度
- 操作数数目
- 可寻址寄存器数目
- 内存组织:字节or字
- 寻址方式:直接、间接、索引
- 字节顺序:大端or小端
小端和大端
字节序byte ordering/endianness
小端(little endian):先存储最低有效字节(到低地址),相对较难找到数字标志位,必须知道存储一个数所需字节数(GIF)
大端(big endian):先存储最高有效字节,更符合阅读习惯(计网、JPEG)
eg:对0x12345678,小端:78563412,大端:12345678
CPU存储数据
- 堆栈型:使用一个堆栈来执行命令,操作数隐式地存放在栈顶,不能随机访问一个堆栈;使用0或1个操作数,add、mult取栈顶两个数计算
eg:POP X、PUSH X
- 累加器型:一个操作数隐式地存放在累加器中,由于累加器暂时存储数据,使得内存通信开销大
eg:ADD X、LOAD X
- 通用寄存器(GPR)型:使用寄存器集合,比累加器更快,但指令更长(因为所有操作数都必须命名)
eg:LOAD R1,R2、ADD Z,R1,R2
GPR广泛被现代计算机体系结构采用,寄存器工作速度比内存快得多,且硬件价格下降,使得增加大量寄存器成为可能,可将GPR架构分为三类
- 存储器-存储器:可能2、3个操作数位于内存中
- 寄存器-存储器:至少一个操作数要在寄存器中,另一个在内存中
- 装入-存储:对数据执行操作,数据必须装入寄存器
堆栈架构计算需要采用后缀表示法(postfix notation/reverse Polish notation)
eg:Z=X×Y+W×U → Z=XY×WU×+
三操作数,第一个操作数往往是目的操作数,三地址指令代码如下
$$ \begin{aligned} &MULT\ R1,X,Y\\ &MULT\ R2,W,U\\ &ADD\ Z,R1,R2 \end{aligned} $$
双操作数,通常有一个地址会指明某个寄存器(不允许两个操作数都存放在内存中),另一个操作数存放在寄存器或内存单元中,代码如下
$$ \begin{aligned} &LOAD\ R1,X\\ &MULT\ R1,Y\\ &LOAD\ R2,W\\ &MULT\ R2,U\\ &ADD\ R1,R2\\ &STORE\ Z,R1\\ \end{aligned} $$
单操作数,单地址指令如MARIE,将指令的运行结果作为目的操作数隐式地存放在一个寄存器(累加器)中,代码如下
$$ \begin{aligned} &LOAD\ X\\ &MULT\ Y\\ &LOAD\ W\\ &MULT\ U\\ &ADD\ TEMP\\ &STORE\ Z\\ \end{aligned} $$
零操作数,代码如下
$$ \begin{aligned} &PUSH\ X\\ &PUSH\ Y\\ &MULT\\ &PUSH\ W\\ &PUSH\ U\\ &MULT\\ &ADD\\ &POP\ Z \end{aligned} $$
有些指令比如HALT,不需要操作数,如果使用定长指令会浪费很大空间,因此采用扩展操作码(expanding opcodes)
指令类型
- 数据传送:内存——寄存器之间
- 算术运算:整数、浮点数
- 布尔逻辑运算指令
- 位操作指令
- I/O指令
- 传送控制指令
- 专用指令
寻址
- 立即寻址(immediate addressing):操作数就是指令中紧跟操作码之后地值,能被立即访问到
- 直接寻址(direct ~):通过直接内存地址给出操作数,可以快速定位到操作数
- 寄存器寻址(register ~):通过寄存器编号定位寄存器中的操作数
- 间接寻址(indirect ~):给出数据的地址值的地址
- 寄存器间接寻址:使用寄存器存储数据的地址值
- 变址寻址(indexed ~):一个变址寄存器存储偏移量,偏移量加上指令的操作数,得到所请求操作数的有效地址
- 基址寻址(based ~):一个基址寄存器存储基地址,此地址的字段表示相对于此基地址的偏移量(对数组、字符串中元素访问很有用)
- 堆栈寻址(stack ~):操作数在栈顶
eg: