1. 核心解构
MIPS 是 RISC 的教科书代表。
- 字长:32位。所有指令都是 32 位长(定长),按字(4字节)对齐。
- 寄存器:32 个通用寄存器 (
$0-$31)。$0($zero):恒为 0。这是硬件层面的/dev/null或const 0,用于清零或空操作。$sp($29):栈指针 (Stack Pointer)。$ra($31):返回地址 (Return Address)。栈溢出攻击的首要目标。
2. 指令格式 (The Big Three)
MIPS 只有三种格式,极致简洁(全都是 32 位指令):
- R 型 (Register):
OP | rs | rt | rd | shamt | funct- 位数:6 + 5 + 5 + 5 + 5 + 6
- 用于寄存器间的运算 (add, sub, or)。无需从内存取
- 典型指令:add sub and or slt(set on less than)
- 特点:操作码
op通常全为 0,靠funct区分功能。 - rs、rt:源寄存器
- rd:目标寄存器
- shamt:位移量,只有在做位移指令时才有用
- I 型 (Immediate):
OP | rs | rt | Immediate(16bit)- 用于带立即数的运算、Load/Store (
lw,sw)、条件分支 (beq). - 位数:6 + 5 + 5 + 16
- 典型指令:addi lw sw(
store word) beq(branch if equal) bne(branch if not equal) - 陷阱:立即数只有 16 位!如果需要 32 位常数,必须用
lui(Load Upper Immediate) +ori拼接。
op(6位):操作码。这里必须有具体的值(不能是0了),直接告诉 CPU 我是addi还是lw。rs(5位):第一个源寄存器(或者基址寄存器)。rt(5位):变形金刚!- 最坑考点:在 I 型指令中,
rt的角色变了! - 如果是运算/取数指令(
addi,lw):它是目的寄存器(接收结果)。 - 如果是存数/分支指令(
sw,beq):它是第二个源寄存器(提供数据)。
- 最坑考点:在 I 型指令中,
Immediate(16位):立即数。- 可以是常数(
addi $1, $2, 100里的 100) - 可以是地址偏移量(
lw $1, 8($2)里的 8)。
- 可以是常数(
- 用于带立即数的运算、Load/Store (
- J 型 (Jump):
OP | Address(26bit)- 用于
j(跳转),jal(跳转并链接/函数调用)。 - 计算:目标地址 =
(PC+4)[31:28] | (Address << 2)。只能在 256MB 区域内跳转。- 原因:需要将 26 位的地址还原为 32 位的地址,才能进行索引
- 32 位 = PC的4 + 26原本 + 2(00),因为只有 …x00 是合法的地址,指令地址是 4 的倍数,所以先左移出两个 0 就可以
- 结果:只能在 范围内跳转
- 用于
注意
汇编的寄存器顺序与指令的寄存器顺序不同! 汇编语法:
- R型:
操作码 目的, 源1, 源2- I型:
操作码 目的, 偏移(基址)
3. 期末/实战考点
- 汇编翻译:
if (i == j) f = g + h; else f = g - h;- 翻译为 MIPS 需要用到
bne(不相等则跳转) 来实现else逻辑。
- 寻址陷阱:
lw $s1, 8($s2)中,8是字节偏移量。如果数组是int A[],访问A[2]的偏移量是 。不要漏乘数据宽度!
4. 关联链接
- IoT安全:大量路由器(如 Cisco)和摄像头使用 MIPS 架构,逆向固件时必须掌握 MIPS 汇编。