MIPS 寄存器组和协处理器CP0

MIPS 寄存器组

MIPS 有 32 个通用寄存器($0-$31),各寄存器的功能及汇编程序中使用约定如下:

下表描述 32 个通用寄存器的别名和用途

;REGISTER

NAME

USAGE

$0

$zero

常量 0 (constant value 0)

$1

$at

保留给汇编器 (Reserved for assembler)

$2-$3

v0v0-v1

函数调用返回值 (values for results and expression evaluation)

$4-$7

a0a0-a3

函数调用参数 (arguments)

$8-$15

t0t0-t7

暂时的 (或随便用的)

$16-$23

s0s0-s7

保存的 (或如果用,需要 SAVE/RESTORE 的)(saved)

$24-$25

t8t8-t9

暂时的 (或随便用的)

$28

$gp

全局指针 (Global Pointer)

$29

$sp

堆栈指针 (Stack Pointer)

$30

$fp

帧指针 (Frame Pointer)

$31

$ra

返回地址 (return address)

下面给以详细说明:
$0: 即 $zero, 该寄存器总是返回零,为 0 这个有用常数提供了一个简洁的编码形式。

      move $t0,$t1
   实际为
       add $t0,$0,$t1
   使用伪指令可以简化任务,汇编程序提供了比硬件更丰富的指令集。

$1: 即 $at,该寄存器为汇编保留,由于 I 型指令的立即数字段只有 16 位,在加载大常数时,编译器或汇编程序需要
把大常数拆开,然后重新组合到寄存器里。比如加载一个 32 位立即数需要 lui(装入高位立即数)和 addi 两条
指令。像 MIPS 程序拆散和重装大常数由汇编程序来完成,汇编程序必需一个临时寄存器来重组大常数,这
也是为汇编 保留 $at 的原因之一。
$2…3:(3:(v0-$v1) 用于子程序的非浮点结果或返回值,对于子程序如何传递参数及如何返回,MIPS 范围有一套约
定,堆栈中少数几个位置处的内容装入 CPU 寄存器,其相应内存位置保留未做定义,当这两个寄存器不够存
放返回值时,编译器通过内存来完成。
$4…7:(7:(a0-$a3) 用来传递前四个参数给子程序,不够的用堆栈。a0-a3 和 v0-v1 以及 ra 一起来支持子程序/过程
调用,分别用以传递参数,返回结果和存放返回地址。当需要使用更多的寄存器时,就需要堆栈(stack)
了,MIPS 编译器总是为参数在堆栈中留有空间以防有参数需要存储。
$8…15:(15:(t0-$t7) 临时寄存器,子程序可以使用它们而不用保留。
$16…23:(23:(s0-$s7) 保存寄存器,在过程调用过程中需要保留(被调用者保存和恢复,还包括 $fp 和 $ra),MIPS
提供了临时寄存器和保存寄存器,这样就减少了寄存器溢出(spilling, 即将不常用的变量放到存储器的过程),
编译器在编译一个叶(leaf) 过程(不调用其它过程的过程)的时候,总是在临时寄存器分配完了才使用需要
保存的寄存器。
$24…25:(25:(t8-t9)(t9) 同 (t0-$t7)
$26…27:(27:(k0,$k1) 为操作系统/异常处理保留,至少要预留一个。异常(或中断)是一种不需要在程序中显示
调用的过程。MIPS 有个叫异常程序计数器(exception program counter,EPC) 的寄存器,属于 CP0 寄存器,
用于保存造成异常的那条指令的地址。查看控制寄存器的唯一方法是把它复制到通用寄存器里,指令 mfc0 (move from system control) 可以将 EPC 中的地址复制到某个通用寄存器中,通过跳转语句(jr),程序可以
返回到造成异常的那条指令处继续执行。MIPS 程序员都必须保留两个寄存器 $k0 和 $k1,供操作系统使用。
发生异常时,这两个寄存器的值不会被恢复,编译器也不使用 k0 和 k1, 异常处理函数可以将返回地址放到这
两个中的任何一个,然后使用 jr 跳转到造成异常的指令处继续执行。
28:(28:(gp) 为了简化静态数据的访问,MIPS 软件保留了一个寄存器:全局指针 gp (global pointer,$gp),全局指针
只想静态数据区中的运行时决定的地址,在存取位于 gp 值上下 32KB 范围内的数据时,只需要一条以 gp 为基
指针的指令即可。在编译时,数据须在以 gp 为基指针的 64KB 范围内。
29:(29:(sp) MIPS 硬件并不直接支持堆栈,你可以把它用于别的目的,但为了使用别人的程序或让别人使用你的程
序, 还是要遵守这个约定的,但这和硬件没有关系。
30:(30:(fp) GNU MIPS C 编译器使用了侦指针 (frame pointer), 而 SGI 的 C 编译器没有使用,而把这个寄存器当作保
存寄存器使用($s8), 这节省了调用和返回开销,但增加了代码生成的复杂性。
31:(31:(ra) 存放返回地址,MIPS 有个 jal (jump-and-link, 跳转并链接) 指令,在跳转到某个地址时,把下一条指令的
地址放到 $ra 中。用于支持子程序,例如调用程序把参数放到 a0 a0~a3, 然后 jal X 跳到 X 过程,被调过程完成后
把结果放到 v0,v0,v1, 然后使用 jr $ra 返回。
另外,MIPS 对 CPU 的控制通过协处理器 0(CP0)来完成。
参考资料: http://hi.baidu.com/qq520131714/blog/item/f28933245603072cd40742a6.html MIPS 汇编小贴士
http://blog.csdn.net/jerryutscn/archive/2010/03/10/5365263.aspx 基于 MIPS 架构的 BackTrace 实现

协处理器

深入浅出 MIPS 三 MIPS 的协处理器 CP0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章