type
status
date
summary
tags
category
icon
password
MIPS(Microprocessor without Interlocked Pipelined Stages,无互锁流水线微处理器)是典型的精简指令集计算机(RISC)架构,具有指令长度固定(32 位)、寻址方式简单、寄存器操作优先等特点,广泛用于嵌入式系统、教学场景及早期服务器领域。其设计核心是 “减少指令复杂度,提升流水线效率”,指令仅与寄存器或少量立即数交互,内存访问需通过专门指令完成。

寄存器

通用寄存器(GPR)

编号
寄存器名称
寄存器描述
0
zero
第0号寄存器,其值始终为0
1
$at
保留寄存器
2-3
$v0-$v1
保留表达式或者函数返回结果
4-7
$a0-$a3
作为函数的前4个参数
8-15
$t0-$t7
临时寄存器
16-23
$s0-$s7
调用子函数时需要保留原参数的寄存器
24-25
$t8-$t9
临时寄存器
26-27
$k0-$k1
保留,中断处理函数时使用
28
$gp
全局指针
29
$sp
堆栈指针,指向栈顶
30
$fp
保存栈指针
31
$ra
保存返回地址
  • $zero:其值始终为0,这种硬连线设计使其可方便用于生成常数0,或通过类似add $t0, $zero, $zero的指令清空其他寄存器,也常用来实现空操作(NOP)。
  • $at:保留给汇编器使用的临时寄存器在将汇编源代码翻译成机器码的过程中,汇编器经常需要处理一些复杂的指令或宏,这些指令在实际的机器指令集中并不直接存在(称为“伪指令”),例如加载一个32位立即数 (li)或一个32位地址 (la)。为了完成这些操作,汇编器需要生成多条原始指令,并需要一个临时寄存器来存放中间计算结果。$at就是为此目的而保留的。
  • $v0-$v1:这两个寄存器用于存储函数的返回值。如果一个函数需要返回一个整型或指针值,通常将其放入$v0中。$v1可用于返回第二个值或64位返回值的高位。
  • $a0-$a3:这四个寄存器用于在函数调用时传递前四个整型或指针参数。这是标准调用约定的一部分,使得参数传递比通过内存栈更快。
  • $t0-$t7:这些是临时寄存器,属于“调用者保存”寄存器。被调用的函数可以随意使用并覆盖它们,因此它们适用于存储不需要在函数调用之间保留的临时变量。
  • $s0-$s7:这些是保存寄存器,属于“被调用者保存”寄存器。如果一个函数要使用它们,它必须首先保存其值,并在返回前恢复。因此,它们适用于存储需要在函数调用中保持不变的局部变量。
  • $t8-$t9:这是另外两个临时寄存器,其特性与 $t0-$t7 相同,也是“调用者保存”的,为程序提供了更多的临时存储空间。
  • $k0-$k1:这两个寄存器保留给操作系统内核使用,通常用于中断和异常处理。
  • $gp:全局指针寄存器,指向静态数据区(存储全局变量和静态变量)的大致中间位置。这允许通过单条指令高效地访问该区域内的数据。
  • $sp:堆栈指针寄存器,始终指向当前栈的顶部。它是管理函数调用栈的核心寄存器,用于分配栈空间、传递额外参数和保存寄存器。
  • $fp:帧指针寄存器,指向当前函数栈帧的开始位置。它提供了一个稳定的基准点来访问栈帧内的元素(如局部变量和参数),简化了调试和代码生成。
  • $ra:返回地址寄存器。当使用 jal 指令调用函数时,下一条指令的地址(返回地址)会自动存入此寄存器。函数通过 jr $ra 指令返回到调用者。

特殊寄存器

  • PC(程序计数器):存下一条要执行的指令地址(MIPS中指令占4字节,因此PC每次自增 4);
  • HI/LO:乘除结果寄存器(mult乘法后,高32位存HI,低32位存LO;div除法后,余数存HI,商存LO)。

字节序

字节序指的是数据在内存中存储的字节顺序,主要分为两种:
  1. 大端序
      • 定义: 数据的最高有效字节存放在最低的内存地址。
      • 类比: 和我们书写数字的顺序类似,比如数字1234,我们先写最高位的“千位”1。
      • 常见架构:网络字节序(TCP/IP协议规定)、旧的 PowerPC、SPARC。
  1. 小端序
      • 定义:数据的最低有效字节存放在最低的内存地址。
      • 类比:先存储个位,再存储十位,类似于我们做竖式计算时从右向左写。
      • 常见架构: x86/x86-64、ARM(通常可配置)。
示例
将一个32位十六进制数0x12345678存入地址0x8000开始的内存中:
内存地址
大端序存储内容
小端序存储内容
0x8000
0x12 (最高位 MSB)
0x78 (最低位 LSB)
0x8001
0x34
0x56
0x8002
0x56
0x34
0x8003
0x78 (最低位 LSB)
0x12 (最高位 MSB)

Mips指令集

特点

1.精简指令集:指令数量少、格式规整、功能简单。绝大多数指令都可以在一个时钟周期内完成执行,这使得处理器控制逻辑非常简单高效。
2.加载-存储架构:这是RISC架构的核心特征。只有 load 和 store 指令可以访问内存(如 lwswlb)。所有算术和逻辑运算指令都只在寄存器之间进行操作,简化了指令执行流程。
3.固定长度指令:所有指令都是4字节长,并且严格对齐到4字节边界,极大地简化了指令的取指和解码过程。
4.流水线效应:最重要的一个效应是分支延迟效应,在分支跳转语句中,后面那条语句叫做分支延迟槽。当程序执行到分支跳转语句时,代码计数器终已经填充好了要跳转的地址但是还没有完成本条指令的时候,后面的指令已经执行了,其本质就是流水线效应。
示例:
当执行jalr指令时,后面那条指令已经执行了,所以strchr函数的参数来自后面的$s0而不是$s2.

指令格式

  • R格式 (寄存器类型): opcode(6) | rs(5) | rt(5) | rd(5) | shamt(5) | funct(6)
  • I格式 (立即数类型): opcode(6) | rs(5) | rt(5) | immediate(16)
  • J格式 (跳转类型): opcode(6) | address(26)
各字段说明
  • opcode:操作码
  • rs:第一个源操作数寄存器
  • rt:第二个源操作数寄存器
  • rd:存放操作结果的目的操作数
  • shamt:位移量
  • funct:Function码,和opcode共同决定R型指令的具体操作方式
  • immediate:立即数二进制码

常用指令

1. 算术运算指令

指令
格式
描述
示例
示例解释
add
R
有符号加法
add $t0, $t1, $t2
$t0 = $t1 + $t2
addu
R
无符号加法
addu $t0, $t1, $t2
$t0 = $t1 + $t2 (不检查溢出)
addi
I
加立即数
addi $t0, $t1, 10
$t0 = $t1 + 10
addiu
I
无符号加立即数
addiu $t0, $t1, 10
$t0 = $t1 + 10 (不检查溢出)
sub
R
有符号减法
sub $t0, $t1, $t2
$t0 = $t1 - $t2
subu
R
无符号减法
subu $t0, $t1, $t2
$t0 = $t1 - $t2 (不检查溢出)
mult
R
有符号乘法
mult $t1, $t2
HI,LO = $t1 * $t2
multu
R
无符号乘法
multu $t1, $t2
HI,LO = $t1 * $t2
div
R
有符号除法
div $t1, $t2
LO = $t1/$t2, HI = $t1 % $t2
divu
R
无符号除法
divu $t1, $t2
LO = $t1/$t2, HI = $t1 % $t2
mfhi
R
从HI寄存器移动
mfhi $t0
$t0 = HI
mflo
R
从LO寄存器移动
mflo $t0
$t0 = LO

2. 逻辑运算指令

指令
格式
描述
示例
示例解释
and
R
按位与
and $t0, $t1, $t2
$t0 = $t1 & $t2
or
R
按位或
or $t0, $t1, $t2
$t0 = ($t1 | $t2)
nor
R
按位或非
nor $t0, $t1, $t2
$t0 = ~($t1 | $t2)
xor
R
按位异或
xor $t0, $t1, $t2
$t0 = $t1 ^ $t2
andi
I
与立即数
andi $t0, $t1, 0xFF
$t0 = $t1 & 0xFF
ori
I
或立即数
ori $t0, $t1, 0xFF
$t0 = $t1 | 0xFF
xori
I
异或立即数
xori $t0, $t1, 0xFF
$t0 = $t1 ^ 0xFF
sll
R
逻辑左移
sll $t0, $t1, 2
$t0 = $t1 << 2
srl
R
逻辑右移
srl $t0, $t1, 2
$t0 = $t1 >>> 2
sra
R
算术右移
sra $t0, $t1, 2
$t0 = $t1 >> 2
sllv
R
可变逻辑左移
sllv $t0, $t1, $t2
$t0 = $t1 << $t2
srlv
R
可变逻辑右移
srlv $t0, $t1, $t2
$t0 = $t1 >>> $t2
srav
R
可变算术右移
srav $t0, $t1, $t2
$t0 = $t1 >> $t2

3. 数据传送指令

指令
格式
描述
示例
示例解释
lw
I
加载字
lw $t0, 4($sp)
$t0 = Memory[$sp + 4]
sw
I
存储字
sw $t0, 4($sp)
Memory[$sp + 4] = $t0
lh
I
加载半字
lh $t0, 4($sp)
$t0 = SignExt(Memory[$sp+4:2])
lhu
I
加载无符号半字
lhu $t0, 4($sp)
$t0 = ZeroExt(Memory[$sp+4:2])
sh
I
存储半字
sh $t0, 4($sp)
Memory[$sp+4:2] = $t0[15:0]
lb
I
加载字节
lb $t0, 4($sp)
$t0 = SignExt(Memory[$sp+4])
lbu
I
加载无符号字节
lbu $t0, 4($sp)
$t0 =ZeroExt(Memory[$sp+4])
sb
I
存储字节
sb $t0, 4($sp)
Memory[$sp+4] = $t0[7:0]
lui
I
加载高位立即数
lui $t0, 0x1234
$t0 = 0x12340000
mfc0
R
从协处理器0移动
mfc0 $t0, $12
$t0 = CP0寄存器12
mtc0
R
移动到协处理器0
mtc0 $t0, $12
CP0寄存器12 = $t0

4. 条件分支指令

指令
格式
描述
示例
示例解释
beq
I
相等则分支
beq $t0, $t1, label
if ($t0 == $t1) goto label
bne
I
不等则分支
bne $t0, $t1, label
if ($t0 != $t1) goto label
bgtz
I
大于零则分支
bgtz $t0, label
if ($t0 > 0) goto label
blez
I
小于等于零则分支
blez $t0, label
if ($t0 <= 0) goto label
bltz
I
小于零则分支
bltz $t0, label
if ($t0 < 0) goto label
bgez
I
大于等于零则分支
bgez $t0, label
if ($t0 >= 0) goto label
slt
R
设置小于
slt $t0, $t1, $t2
$t0 = ($t1 < $t2) ? 1 : 0
sltu
R
设置无符号小于
sltu $t0, $t1, $t2
$t0 = ($t1 < $t2) ? 1 : 0
slti
I
设置小于立即数
slti $t0, $t1, 10
$t0 = ($t1 < 10) ? 1 : 0
sltiu
I
设置无符号小于立即数
sltiu $t0, $t1, 10
$t0 = ($t1 < 10) ? 1 : 0

5. 跳转指令

指令
格式
描述
示例
示例解释
j
J
跳转
j label
goto label
jal
J
跳转并链接
jal func
$ra = PC+8; goto func
jr
R
跳转至寄存器
jr $ra
goto $ra
jalr
R
跳转并链接至寄存器
jalr $t0
$ra = PC+8; goto $t0

6. 特殊指令

指令
格式
描述
示例
示例解释
syscall
R
系统调用
syscall
根据$v0的值执行系统调用
break
R
断点异常
break 10
触发断点异常,代码10
nop
R
空操作
nop
无操作,常用于延迟槽
 
pwn知识点复习和拓展IO_FILE结构以及vtable相关知识
Loading...