Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2706976
  • 博文数量: 505
  • 博客积分: 1552
  • 博客等级: 上尉
  • 技术积分: 2514
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-23 18:24
文章分类

全部博文(505)

文章存档

2019年(12)

2018年(15)

2017年(1)

2016年(17)

2015年(14)

2014年(93)

2013年(233)

2012年(108)

2011年(1)

2009年(11)

分类: LINUX

2013-04-18 09:18:41

费了好大的劲,终于知道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的使用。 

阅读(7359) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~