1. 核心解构

MIPS 是 RISC 的教科书代表。

  • 字长:32位。所有指令都是 32 位长(定长),按字(4字节)对齐。
  • 寄存器:32 个通用寄存器 ($0 - $31)。
    • $0 ($zero)恒为 0。这是硬件层面的 /dev/nullconst 0,用于清零或空操作。
    • $sp ($29):栈指针 (Stack Pointer)。
    • $ra ($31):返回地址 (Return Address)。栈溢出攻击的首要目标

2. 指令格式 (The Big Three)

MIPS 只有三种格式,极致简洁(全都是 32 位指令):

  1. 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:位移量,只有在做位移指令时才有用
  2. 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):它是第二个源寄存器(提供数据)。
    • Immediate (16位)立即数
      • 可以是常数(addi $1, $2, 100 里的 100)
      • 可以是地址偏移量(lw $1, 8($2) 里的 8)。
  3. 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 汇编。