PIC----代码无关设计

编译器在编译一段程序时,要经过三个步骤:编译,链接和加载。在链接时,要对所有目标文件进行重定位,建立符号引用规则,同时为变量,函数等分配地址。程序执行时,把代码加载到链接时指定的地址空间,以保证程序在执行过程中对变量,函数等符号的正确引用,是程序正常运行。
但是,在操作系统中,一个进程通常从硬盘等二级存储设备拷贝到内存中去执行,这两者的地址是不同的,因此操作系统要对这个进程进行重定位,才能正确运行该进程。
在设计系统引导程序如bootloader时,也要对代码进行重定位。因为我们为了提高速度,需要将bootloader从ROM拷贝到RAM中去执行,这两者的地址也不同。
拷贝bootloader的这一小段代码是上电后就开始执行的,这些代码即使不在链接时指定的地址空间也能正确运行,这就是位置无关代码(position independent co de)。

PIC的特点是,它被加载到任意地址空间都可以正确的执行。其原理是PIC对常量和函数入口地址的操作都是基于PC+偏移量的寻址方式。即使程序被移动,但是PC也变化了,而偏移量是不变的,所以程序仍然可以找到正确的入口地址或者常量。
例如:SH里面的BRA指令就可以用来设计PIC
BRA _main
编译后:
_main * 2 + PC -> PC

在SH体系中,MOV指令操作一个常数或者函数入口地址,比如:
MOV.L #_main, R0
MOV.L #H'FF010010,R0
编译器通常将这个常数或者地址存放在(2)里面的literal pool中。
请注意:literal pool里面实际上只存放绝对地址或者常量!!
因此,我们可以得出一个结论:
使用literal pool并不能产生位置无关代码,因为在literal pool里面存放的是函数入口的绝对地址或者常数,移动程序后,这些内容并没有改变。
在设计bootloader时,一个可行的方法是,将bootloader链接到RAM里面的指定位置(0x1000000),然后将bootloader加载到ROM里面的地址0x0处,CPU上电从ROM地址0x0执行。此时的bootloader的运行地址为0x0,而链接地址为0x1000000。由于bootloader头部的一小段代码是位置无关代码,它仍然可以在地址0x0处运行,并将整个bootloader拷贝到RAM地址的0x1000000处,然后清除bss段并设置堆栈,最后将main()的绝对地址(链接时的地址),比如0x1000100装入PC,并跳转到RAM里去。
MOV.L #_main, R0
JSR @R0
NOP
执行到这里后,程序就从ROM跳转到RAM里面了。
指令MOV.L _main, R0之前的所有指令都是位置无关代码。由于MOV指令会把main的绝对地址0x1000100放入literal pool,因此执行JSR @R0之后,程序就跳转到RAM里面的0x1000100处了。
至此,bootloader就在链接时指定的地址处运行了,这时它就可以在RAM里使用literal pool里面的绝对地址来进行函数的跳转或者操作常数了。这与重定位之前的情况是一样的。

值得一提的是,在有操作系统的系统中,不可能把进程都用PIC来写(编译器不能将C程序完全编译成PIC),由于进程可以随意的从硬盘加载到内存中,因此必须从硬件上来实现重定位,比如重定位寄存器。x86提供代码段,数据段,堆栈段重定位寄存器,操作系统通过修改这些寄存器,来重定位内存中的代码,数据和栈。


扩展地址:http://blog.csdn.net/phunxm/article/details/8905309

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值