分类: LINUX
2013-08-15 23:12:03
原文地址:mips中gp寄存器的用法 作者:laoyouji
费了好大的劲,终于知道gp寄存器的用法了。
首先说说gp寄存器出现的原因吧,由于RISC体系的CPU,每条指令都是32Bit,而地址总线也是32Bit,这样,就不可能通过一条指令来实现Memory的访问。
MIPS中,访问Memory的指令格式为:
lw r1, offset(r2)其中,offset为16Bit,也就是说,最多能访问以r2为基地址,前后32K的空间。
于是这个时候,gp就闪亮登场了。
我 们知道,GCC在编译过程,会将变量分别放在data,bss,common等段。而编译mips程序时,会将小变量放入 sdata,sbss,scommon等段。这个大小由编译选项-G来决定。-G0则表示不使用小数据段。默认是-G8,表示小于或等于8 byte的数据将放入小变量区。
这样的话,在上电时给gp初始化一个值,那么,所有小变量区的变量就可以通过
lw r1, offset(gp)来访问了。
那么,GCC怎么知道gp初始化的值呢?只要在link文件中添加_gp符号,连接器就会认为这是gp的值。我们在上电时,将_gp的值赋给gp寄存器就行了。
* gp: 如果存在一个全局指针,它将指向运行
时决定的,你的静态数据(static data)区域的一个位置。这意味着,利用gp作基指针,在gp指针32K左右的数据存取,系统只需要一条指令就
可完成。如果没有全局指针,存取一个静态数据区域的值需要两条指令:一条是获取有编译器和loader决定好的32位的地址常量。另外一条是对数据的真正
存取。为了使用gp, 编译器在编译时刻必须知道一个数据是否在gp的64K范围之内。通常这是不可能的,只能靠猜测。一般的做法是把
small global data (小的全局数据)放在gp覆盖的范围内(比如一个变量是8字节或更小),并且让linker报警如果小的全局数据仍
然太大从而超过gp作为一个基指针所能存取的范围。
并不是所有的编译和运行系统支持gp的使用。