位置无关代码(PIC)在 Bootloader 中的应用
来源:互联网 发布:风云万象 厦门网游网络 编辑:程序博客网 时间:2024/06/05 00:13
华东师范大学 作者: 黄振华 李外云 刘锦高
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
引 言
基于位置无关代码PIC( PositionOIndependent Code) 的程序设计在嵌入式应用系统开发中具有重要的作用,尤其在裸机状态下开发Bootloader 程序及进行内核初始化设计;利用位置无关的程序设计方法还可以在具体应用中用于构建高效率动态链接库,因而深入理解和熟练掌握位置无关的程序设计方法,有助于开发人员设计出结构简单、清晰的应用程序。本文首先介绍位置无关代码的基本概念和实现原理,然后阐述基于ARM 汇编位置无关的程序设计方法和实现过程,最后以Bootloader 程序设计为例,介绍了位置无关程序设计在Bootloader 程序设计中的作用。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
位置无关代码及程序设计方法
1. 基本概念与实现原理
应用程序必须经过编译、汇编和链接后才变成可执行文件,在链接时,要对所有目标文件进行重定位( reloca2tion) ,建立符号引用规则,同时为变量、函数等分配运行地址。当程序执行时,系统必须把代码加载到链接时所指定的地址空间,以保证程序在执行过程中对变量、函数等符号的正确引用,使程序正常运行。在具有操作系统的系统中,重定位过程由操作系统自动完成。
在设计Bootloader 程序时,必须在裸机环境中进行,这时Bootloader 映像文件的运行地址必须由程序员设定。通常情况下,将Bootloader 程序下载到ROM 的0x0 地址进行启动,而在大多数应用系统中,为了快速启动,首先将Bootloader 程序拷贝到SDRAM 中再运行。一般情况下,这两者的地址并不相同,程序在SDRAM 中的地址重定位过程必须由程序员完成。实际上,由于Bootloader 是系统上电后要执行的第一段程序,Bootloader 程序的拷贝和在这之前的所有工作都必须由其自身来完成,而这些指令都是在ROM 中执行的。也就是说,这些代码即使不在链接时所指定的运行时地址空间,也可以正确执行。这就是位置无关代码,它是一段加载到任意地址空间都能正常执行的特殊代码。
位置无关代码常用于以下场合:
- 程序在运行期间动态加载到内存;
- 程序在不同场合与不同程序组合后加载到内存(如共享的动态链接库) ;
- 在运行期间不同地址相互之间的映射( 如Boot2loader 程序) 。
LDR PC , = main上面的LDR 汇编伪指令编译后的结果为:
LDR PC , [ PC , OFFSET_ TO_L POOL ]…L POOL DCD main可见, 虽然LDR 是把基于PC 的一个存储单元 L POOL 的内容加载到PC 中,但该存储单元中保存的却是链接时所决定的main 函数入口的绝对地址,所以main函数实际所在的段不是位置无关。
②位置无关的常量访问。
GPIO_BASE EQU 0x40e00000 ;GPIO 基址寄存器地址GPDR0 EQU 0x00c ;相对于GPIO 基址寄存器的偏移量init_ GPDR0 EQU 0xfffbfe00 ;寄存器GPDR0 初值LDR R1 , = GPIO_BASELDR R0 , = init_GPDR0STR R0 , [ R1 , # GPDR0 ]上述汇编代码段经编译后的结果为:
LDR R1 , [ PC , OFFSET_ TO_GPIO_BASE]LDR R0 , [ PC , OFFSET_ TO_init_GPDR0 ]STR R0 , [ R1 , # 0xc ]…GPIO_BASE DCD 0x40e00000GPDR0 DCD 0x00cinit_ GPDR0 DCD 0xfffbfe00可见,LDR 伪指令实际上使用基于PC 的偏移量来对符号常量GPIO_BASE 和init _ GPDR0 进行引用,因而是位置无关的。
由此可以得出如下结论:使用LDR 伪指令将一个常量读取到非PC 的其他通用寄存器中可实现位置无关的常量访问;但将一个地址值读取到PC 中进行程序跳转时,跳转目标则是位置相关的。
其他被ROPI 段中的代码引用的必须是绝对地址,或者是基于可读写位置无关( RWPI) 段的静态基址寄存器的可写数据。
OU TPU T_ARCH(arm)EN TRY(_start)SECTIONS { .= BOOTADDR ; /*Bootloader 的起始地址*/ _ _boot_start = .; .text AL IGN(4): {/* 代码段. text */ *( .text) } .data AL IGN(4): {/* 数据段. data */ *( .data) } .got AL IGN(4): {/* 全局偏移量表.got 段 */ *( .got) } _ _boot_end = .; /* Bootloader 映像文件的结束地址 */ .bss AL IGN(16): { /* 堆栈段. bss */ _ _bss_start = .; *( .bss) _ _bss_end = .; }}
. section . text. globl _start_start : B reset /*复位异常*/ … /*其他异常处理代码*/reset : … /* 复位处理程序*/copy_boot : /* 拷贝Bootloader 到SDRAM */ LDR R0 , = 0x0 LDR R1 , = _ _boot_start LDR R2 , = _ _boot_end1 : LDRMIA R0 !, { R3 - R10 } STRMIA R1 !, { R3 - R10 } CMP R1, R2 BL T 1bclear_bss : … /*清零. bss 段*/ BL init_Stack /*初始化堆栈*/ LDR PC, = main /*跳转到阶段2 的C 程序入口 */end程序入口为_start ,即复位异常,所有其他异常向量都使用相对跳转指令B 来实现,以保证位置无关特性。在完成基本的硬件初始化后,利用链接脚本传递过来_ _boot_start 和_ _boot_end 的参数,将Bootloader 映像整个拷贝到指定的SDRAM 空间,并清零. bss 段,初始化堆栈后,程序将main 函数入口的绝对地址赋给PC ,进而跳转到SDRAM 中继续运行。程序在跳转到main 函数之前,所有的代码都在ROM 中运行,因而必须要保证代码的位置无关性,所以在调用初始化GPIO、存储系统和堆栈等子程序时,都使用相对跳转指令来完成。
①简化设计,方便实现系统的快速引导。
②实现复位处理智能化。
ADR R0, _start /*读取当前PC 附近的_start 标号所在指令地址*/LDR R1, = _ _boot_start /*读取Bootloader 在SDRAM的起始地址*/CMP R0, R1BEQ clear_bss上述代码中的ADR 指令读取的_start 标号地址由指令的执行地址决定。若是从SDRAM 中的Bootloader 启动,则上述比较结果相等,程序直接跳转到clear_bss 标号地址处执行, 这样可以避免存储系统的重新初始化和Bootloader 的拷贝过程; 若是上电或硬件复位, 程序从ROM 启动,则上述比较结果不等,程序便进行包括系统初始化和Bootloader 拷贝等过程的全面复位处理操作。
③便于调试。
本文所介绍的基于位置无关的程序设计是通过基于PC 或基址寄存器的符号引用规范来实现的。这种方法在实际系统开发中应用广泛,既能用于引导程序的设计,也可用于一般的应用程序或嵌入式共享库的开发。而在Bootloader 的设计中引入位置无关代码,可以使程序结构更为简单清晰,并能避免地址重映射并从SDRAM 进行快速系统引导;引用位置无关的设计方法使Bootloader 的复位处理功能更为灵活,还使得在SDRAM 中和在ROM 中进行程序调试具有相同的效果.
- 位置无关代码(PIC)在 Bootloader 中的应用
- ARM的位置无关程序设计在Bootloader中的应用
- ARM的位置无关程序设计在Bootloader中的应用
- 位置无关代码PIC
- 共享库中的位置无关代码(PIC)
- x64共享库中的位置无关代码(PIC)
- bootloader与linux中位置无关代码(PIC)的分析理解
- bootloader与linux中位置无关代码(PIC)的分析理解
- bootloader与linux中位置无关代码(PIC)的分析理解
- bootloader与linux中位置无关代码(PIC)的分析理解
- bootloader与linux中位置无关代码(PIC)的分析理解
- bootloader与linux中位置无关代码(PIC)的分析理解
- bootloader与linux中位置无关代码(PIC)的分析理解
- 基于位置无关代码PIC的程序设计
- 位置无关代码(PIC)的思考
- 位置无关代码(PIC)的思考
- 位置无关代码(PIC)的思考
- 位置无关代码(PIC)的思考
- poj 3373
- 爱学习,爱编程,爱咖啡可乐 爱挑战,爱钻研,爱打游戏 爱晚起,也爱工作到深夜 我擅长技术,崇尚简单和懒惰 我神秘而孤僻,沉默而爱憎分明 Don't Panic! I'm a programmer
- nodejs简单应用五( 提高页面加载速度---304与压缩)
- 黑马程序员08-GUI自我提问
- 关于ppc的32位立即数加载问题
- 位置无关代码(PIC)在 Bootloader 中的应用
- ZOJ 1730 Crazy Tea Party
- pics
- POJ 1700 Crossing River
- 数据结构笔记二(20120825)
- 黑马程序员09-网络编程自我提问
- OpenSSH
- Meta-Character and regexp
- Android抽屉实现