汇编语言之一——MIPS32指令集
cancan123456 · · 个人记录
这里介绍的是 MIPS32 Release 1 的指令集。
一、相关信息
内置寄存器
MIPS 是 32 位的 CPU,有 32 个 32 位的寄存器,用途如下图所示:
| 编号 | 助记符 | 用途 |
|---|---|---|
| 0 | $zero |
永远为 0 |
| 1 | $at |
保留寄存器,共汇编器使用 |
| 2-3 | $v0-v1 |
保存表达式或函数返回结果 |
| 4-7 | $a0-a3 |
作为函数的前 4 个参数 |
| 8-15 | $t0-t7 |
供汇编程序使用的临时寄存器 |
| 16-23 | $s0-s7 |
子函数使用时需要先保存原寄存器的值 |
| 24-25 | $t8-t9 |
供汇编程序的临时寄存器,和 t0-t7 一样 |
| 26-27 | $k0-k1 |
保留寄存器,中断处理函数使用 |
| 28 | $gp |
全局指针 |
| 29 | $sp |
堆栈指针,指向堆栈的栈顶 |
| 30 | $fp |
保存栈指针 |
| 31 | $ra |
返回地址 |
详细的解释:
-
$0:即$zero,该寄存器总是返回 0,为 0 这个有用常数提供了一个简洁的编码形式。在 MIPS 处理器的通用寄存器中,没有任何帮助运算判断的标志寄存器,要实现相应的功能时,都是通过测试两个寄存器是否相等完成的。 MIPS 编译器常常会使用slt, beq, bne等指令和由寄存器$0获得 0 值产生比较所有的比较条件,如相等、不等、小于等于、大于、大于等于。还可以用add指令创建move伪指令,如move $t0, $t1; $t0=$t1实际为add $t0, $0, $t1; $t0 = $t1 + 0。使用 MIPS 伪指令可以简化任务。 -
$1 ($at):该寄存器为汇编器保留,用做汇编器的暂时变量。 -
$2-$3 ($v0-$v1): 用于存放子程序的返回值或非浮点结果。当这两个寄存器不够存放返回值时,编译器通过内存来完成。 -
$4-$7 ($a0-$a3):用于将前 4 个参数传递给子程序,不够的用堆栈处理。$a0-$a3, $v0-$v1和ra一起完成子程序函数调用过程,分别用以传递参数、返回结果和存放返回地址。当需要使用更多的寄存器时就需要堆栈了。MIPS 编译器总是为参数在堆栈中留有空间,以防有参数需要存储。 -
$8-$15($t0-$t7): 一个子函数可以不用保存并随意使用这些寄存器。在进行表达式计算时,这些寄存器是非常好的临时变量。在使用时需要注意,当调用一个子函数时,这些寄存器的值有可能被子函数破坏。 -
$16-$23($s0-$s7):子函数必须保证当函数返回时这些寄存器的内容将恢复到函数调用以前的值,或者子函数里不使用这些寄存器或把它们保存在堆栈上并保存在函数退出时恢复。这种约定使这些寄存器非常适合作为寄存器变量,或者用于存放一些函数调用期间必须保存的原值。 -
$24-$25 ($t8-$t9):同$t0-$t7,作为$t0-$t7寄存器补充。 -
$26-$27 ($k0-$k1):通常被中断或异常处理程序使用,以保存一些系统参数。 -
$28 ($gp):C 语言中有两种存储类型,分别是自动型和静态型。自动变量是一个函数中的局部变量。静态变量在进入和退出一个函数时都是存在的。为了简化静态数据的访问, MIPS 保留了一个寄存器作为全局指针gp在编译时,数据需要在以gp为基指针的 64KB 范围内。 -
$29 ($sp):MIPS 硬件并不直接支持堆栈,x86 有单独的 PUSH 和 POP 指令,而 MIPS 没有单独的栈操作指令,所有对栈的操作都是统一的内存访问方式,单这并非不影响 MIPS 使用堆栈。在发生函数调用时,调用者把函数调用之后要用的寄存器压入堆栈,被调用者把返回地址寄存器$ra(并非任何时候都保存$ra)和保留寄存器压入堆栈。同时,调整堆栈指针,并在返回时从堆栈中恢复寄存器。 -
$30 ($fp):不同编译器可能对该寄存器使用方法不同。GNU MIPS C 编译器使用了栈指针(Frame Pointer)。SGI 的 C 编译器则没有使用栈指针,只是把这个寄存器当成保存寄存器使用(把它当做$s8),这虽然节省了调用和返回开销,但增加了代码生成的复杂度性。 -
$31 ($ra):存放返回地址。MIPS 有一个jar(jump-and-link,跳转并链接)指令,在跳转到某个地址时可把下一条指令的地址放到$ra中,用于支持子程序。例如,调用程序把参数放到$a0-$a3中,jar X指令跳到X过程,被调用时需要保存的寄存器为$a0-$a3, $s0-$s7, $gp, $sp, $fp, $ra。
虽然但是,上面的这些玩意仅仅是约定。实际上,除了 $0 和 $31 之外,你都可以随便用。
特殊寄存器
程序计数器 PC,用于乘除运算的 HI 和 LO。
在乘法的时候 HI 保存高 32 位,LO 是低 32 位。
在出发的时候 HI 保存商,LO 是余数。