MIPS体系结构(1)

来源:互联网 发布:分销商城源码 编辑:程序博客网 时间:2024/05/17 07:43

MIPS中的寄存器

32个通用寄存器:

寄存器编号  助记符     用法
0            zero       永远返回值为0
1            at         用做汇编器的暂时变量
2-3          v0, v1     子函数调用返回结果
4-7          a0-a3      子函数调用的参数
8-15         t0-t7      暂时变量,子函数使用时不需要保存与恢复
24-25        t8-t9
16-23        s0-s7      子函数寄存器变量。子函数必须保存和恢复使用过的变量在函数返回之前,从而调用函数知道这些寄存器的值没有变化。
26,27        k0,k1      通常被中断或异常处理程序使用作为保存一些系统参数
28           gp         全局指针。一些运行系统维护这个指针来更方便的存取“static“和”extern"变量。
29           sp         堆栈指针
30           s8/fp      第9个寄存器变量。子函数可以用来做桢指针
31           ra         子函数的返回地址

寄存器名约定与使用:

*at: 这个寄存器被汇编的一些合成指令使用。如果你要显式地使用这个寄存器(比如在异常处理程序中保存和恢复寄存器),有一个汇编directive 可被用来禁止汇编器在directive 之后再使用at 寄存器(但是汇编的一些宏指令将因此不能再可用)。 
*v0, v1: 用来存放一个子程序(函数)的非浮点运算的结果或返回值。如果这两个寄存器不够存放需要返回的值,编译器将会通过内存来完成。
*a0-a3: 用来传递子函数调用时前4 个非浮点参数。在有些情况下,这是不对的。
* t0-t9: 依照约定,一个子函数可以不用保存并随便的使用这些寄存器。在作表达式计算时,这些寄存器是非常好的暂时变量。编译器/程序员必须注意的是,当调用一个子函数时,这些寄存器中的值有可能被子函数破坏掉。
*s0-s8: 依照约定,子函数必须保证当函数返回时这些寄存器的内容必须恢复到函数调用以前的值,或者在子函数里不用这些寄存器或把它们保存在堆栈上并在函数退出时恢复。这种约定使得这些寄存器非常适合作为寄存器变量或存放一些在函数调用期间必须保存原来值。
* k0, k1: 被OS 的异常或中断处理程序使用。被使用后将不会恢复原来的值。因此它们很少在别的地方被使用。
* gp: 如果存在一个全局指针,它将指向运行时决定的,你的静态数据(static data)区域的一个位置。这意味着,利用gp 作基指针,在gp 指针32K 左右的数据存取,系统只需要一条指令就可完成。如果没有全局指针,存取一个静态数据区域的值需要两条指令:一条是获取有编译器和loader 决定好的32 位的地址常量。另外一条是对数据
的真正存取。为了使用gp, 编译器在编译时刻必须知道一个数据是否在gp 的64K 范围之内。通常这是不可能的,只能靠猜测。一般的做法是把small global data (小的全局数据)放在gp 覆盖的范围内(比如一个变量是8 字节或更小),并且让linker 报警如果小的全局数据仍然太大从而超过gp 作为一个基指针所能存取的范围。并不是所有的编译和运行系统支持gp 的使用。
*sp: 堆栈指针的上下需要显示的通过指令来实现。因此MIPS 通常只在子函数进入和退出的时刻才调整堆栈的指针。这通过被调用的子函数来实现。sp 通常被调整到这个被调用的子函数需要的堆栈的最低的地方,从而编译器可以通过相对於sp 的偏移量来存取堆栈上的堆栈变量。详细可参阅10.1 节堆栈使用。
* fp: fp 的另外的约定名是s8。如果子函数想要在运行时动态扩展堆栈大小,fp 作为桢指针可以被子函数用来记录堆栈的情况。一些编程语言显示的支持这一点。汇编编程员经常会利用fp 的这个用法。C 语言的库函数alloca()就是利用了fp 来动态调整堆栈的。如果堆栈的底部在编译时刻不能被决定,你就不能通过sp 来存取堆栈变量,因此fp 被初始化为一个相对与该函数堆栈的一个常量的位置。这种用法对其他函数是不可见的。
* ra: 当调用任何一个子函数时,返回地址存放在ra 寄存器中,因此通常一个子程序的最后一个指令是jr ra.
子函数如果还要调用其他的子函数,必须保存ra 的值,通常通过堆栈。
原创粉丝点击