机器指令概述
机器指令是计算机硬件可以执行的表示一种基本操作的二进制代码
要素
操作码+操作数(操作数地址)
- 操作码:指明操作类型
- 操作数 (地址):指明操作数的位置或操作数本身
- 源操作数地址:参加操作的操作数的地址,可能有多个
- 目的操作数地址:保存操作结果的地址
- 下条指令的地址:少数非顺序执行的指令需要指明
类型
- 数据传输指令:寄存器与存储器之间,寄存器之间传递数据
- 算术/逻辑运算指令:寄存器(或存储器)中整型数或逻辑型数据的运算操作,以及处理浮点数运算的浮点运算指令
- 程序控制指令:控制程序执行顺序,条件转移或跳转,循环控制指令,子程序调用和返回等
- 其它指令:多用户多任务系统中的特权指令;复位/暂停/空操作等指令
操作码
- 固定长度操作码 (如 MIPS)
- 硬件设计简单
- 指令译码时间开销较小
- 指令空间效率较低
- 可变长度操作码(如 80x86)
- 硬件设计相对复杂
- 指令译码时间开销较大
- 指令空间利用率较高
操作数
类型
- 数值(无符号、定点、浮点)
- 逻辑型数、字符
- 地址(操作数地址、指令地址)
位置
- 存储器(存储器地址)
- 寄存器(寄存器地址)
- 输入输出端口(输入输出端口地址)
存储方式
- 大端次序:最高有效字节存储在地址最小位置
- 小端次序:最高有效字节存储在地址最大位置
寻址方式
基本概念
- 形式地址(Add):指令中直接给出的操作数的地址编码
- 有效地址(EA):操作数在内存中的地址,可由形式地址和寻址方式计算得到
- 寻址方式(Mod):根据形式地址,计算出操作数有效地址的方法(算法)
常用寻址方式
类别
- 立即寻址:
- 操作数直接在指令代码中给出,如
addi $s1, $s2, 100 - 操作数是指令内嵌常数,不作为独立的数据存储在存储器中,没有地址。
- 操作数直接在指令代码中给出,如
- 寄存器直接寻址:
- 操作数在寄存器中,指令地址字段给出寄存器的地址,如
add $s1, $s2, $s3 - 伪直接寻址:MIPS 的 J 类型指令,需要对立即数进行一些拼接得到最终地址,地址给出下一条指令位置。
- 操作数在寄存器中,指令地址字段给出寄存器的地址,如
- 寄存器间接寻址:
- 操作数在存储器中,指令地址字段中给出的寄存器的内容,是操作数在存储器中的地址(MIPS 中不存在对应的专门指令,用基址寻址覆盖了这个方式)
- 基址寻址:
- 操作数在存储器中,指令地址字段给出一基址寄存器和一形式地址,基址寄存器的内容与形式地址之和是操作数的内存地址,即 。如
lw $s1, 4($zero) - MIPS 中,如果 offset 为 0,可以起到和寄存器间接寻址一样的效果,如
lw $s1, 0($s2) - 优点:较短的形式地址长度,可以实现较大的存储空间的寻址
- 操作数在存储器中,指令地址字段给出一基址寄存器和一形式地址,基址寄存器的内容与形式地址之和是操作数的内存地址,即 。如
- 变址寻址:
- 操作数在存储器中,指令地址字段给出一基址寄存器和一变址寄存器、还可能有一偏移量,之和是操作数的内存地址。有的系统中,变址寻址完成后,变址寄存器的内容将自动进行调整。 常用于数组操作。

- MIPS 中不存在,依靠分步算数和基址寻址完成,如
sll $t1, $i, 2; add $t1, $t1, $a; lw $t0, 0($t1)。
- 相对寻址:
- 基址寻址的特例,程序计数器 PC 作为基址寄存器。 指令中给出的形式地址作为位移量,二者之和是操作数的内存地址。
- 堆栈寻址:
- 堆栈指针(SP)是一个特殊寄存器部件, 指向栈顶
- 例如 X86 由
PUSH和POP进行,指令内不用指明 SP。 - MIPS 不存在专门指令实现,是通过操作
$sp加基址寻址,实现栈访问。
确定
- 在操作码中给定寻址方式(如 MIPS)
- 指令中专门的寻址方式位(如 x86)

指令集系统架构(ISA)种类
有堆栈型、累加器型、通用寄存器型,大部分ISA都可归类为通用寄存器型,分为:
- Register-Memory式ISA(如X86):多种指令可以访问内存;存在寄存器操作数和内存操作数直接运行的指令
- Register-Register (Load-Store) 式ISA(如 MIPS):只有取数(LOAD)和存数(STORE)指令可以访问内存;运算指令操作数全部为寄存器操作数
Load-Store 是 ISA 的趋势。
MIPS 指令系统
特点
- MIPS只有3种指令格式(R,I,J),32位固定长度指令格式
- 最多3地址指令
- 对于Load/Store指令,用基址寻址,没有间接寻址
- 简单转移条件(与0比较,或者比较两个寄存器是否相等)
寄存器约定

存储器
- 字节寻址
- 小端存储
指令格式
R类型
R for register,寄存器类型。
但是注意机器代码格式:(尤其是三个寄存器的顺序,和一般的写法顺序不同)

op为0,由funct决定操作;
rs、rt为源,rd为目的。
I类型
I for immediate,立即数类型。
机器代码:

rs、imm为源,rt为目的/源;
imm以补码表示。
J类型
J for jump,跳转指令。
机器代码:

addr为26位,但是由于指令字对齐,末了两位为0(4的倍数),而前面4位由PC + 4最高4位决定。
指令类型
运算
逻辑
- R 类型
and,or,xor,nornot:nor $s1 $s1 $0
- I 类型(0 扩展)
andi,ori,xorinori:ori $s1 $s1 imm; nor $s1 $s1 $0
生成常数
- 16 位常数赋值:
addiaddi $s0 $0 0x4f3c- 32 位常数赋值:
luithenorilui $s0, 0x6d5e # $s0 = 0x6d5e0000 ori $s0, $0, 0x4f3c # $s0 = 0x6d5e4f3c(
lui:加载立即数到高位)
移位
sll,srl,sra(虽然有数字,但是是R类型,数字对应shamt位)sllv,srlv,srav(可变移位指令)(sllv rd rt rs, 顺序和大多R指令不同)
乘除法
mult,divmultu,divu乘法中,hi装高位,lo装低位;
除法中,hi装余数,lo装商。
量值比较
slt,sltu,slti,sltiu:小于置 1
跳转与分支
条件分支
beq:相等跳转bne:不相等跳转bgez:大于等于0时跳转bgtz:大于0时跳转blez:小于等于0时跳转bltz:小于0时跳转
这里的跳转是根据offset,PC = (PC + 4) + signed_extend(offset << 2)。因此跳转范围为 256 KB。即: KB
跳转指令
j:跳转jal:跳转并链接(将返回地址保存到$ra中)jr:跳转寄存器
跳转范围:
- J 类型的指令如
j,jal跳转范围有限,为 256 MB。Addr = addr << 2共 26 + 2 = 28 位, MB
jr,jalr为 R 类型,跳转到寄存器存储的地址,32 位,可跳 4 GB。
访存
字
lwsw
字节/半字
lb,lbu(lh,lhu):将字节(半字)装入寄存器,进行有/无符号扩展sb(sh):将寄存器最低字节(半字)装入存储器指定地址
特殊指令
- 系统调用
syscall - 断点
break
函数调用
调用与返回
- 调用:
jal - 返回:
jr
传入参数与返回值
- 参数:
- a3
- 不足时,开辟栈空间存储,caller负责
- 返回值:v1(低32位和高32位)
栈
函数分配栈空间存储局部变量,并在返回前回收栈空间。
结构:

$sp寄存器存储栈顶位置指针,指向栈顶。需要栈空间时缩小栈指针,使得栈向下增长。
应用:保存和恢复函数使用的寄存器。
分为受保护和不受保护寄存器,分别又对应callee-save和caller-save寄存器。

局部变量存在s寄存器,需要恢复保存;如果局部变量过多,也开辟栈空间存储,尤其是局部数组。
步骤:
- Makes space on the stack to store the values of one or more registers.
- Stores the values of the registers on the stack.
- Executes the function using the registers.
- Restores the original values of the registers from the stack.
- Deallocates space on the stack
递归函数调用

递归函数这样来看、写,分为三部分。
寻址方式
读写操作数
- 寄存器直接寻址:R类型
- 立即寻址:部分I类型,如
addi,lui - 基址寻址:存储器访问指令,如
lw,sw
写PC的方式
内存映射

其他概念
伪指令
在转换为机器代码的时候,伪指令将转化为一条或者多条MIPS指令。
异常
- 硬件引发:中断
- 软件引发:自陷