什么是重定位?为什么要代码重定位?
要弄清楚上面的这两个问题,首先要理解下面这几个概念
一、编码
(1)位置无关编码:PIC,可执行程序运行时与代码在内存中的地址无关,代码中没有使用绝对地址,而是使用的相对地址。(例如:B、BL、MOV等指令)
(2)位置有关编码:可执行程序运行时与代码在内存中的地址有关系。(例如:LDR PC, =MAIN等指令)
二、地址
(1)链接地址:程序编译链接时指定的地址(使用makefile或者链接脚本可以指定链接地址)
(2)运行地址:程序在内存中实际运行的地址。
参考资料:http://blog.csdn.net/linux_103/article/details/8888427
三、S5PV210的启动
在uboot中的启动方式,将整个uboot分为2个部分(BL1和BL2),是分别加载到内存中去运行的。在这个过程中,程序的链接地址和运行地址就很可能不是相同的了,但是在代码中又有一些位置有关码,为了使得程序可以正常的运行,就必须使用重定位来解决。(关于S5PV210的启动在另一篇文章里有介绍)
四、如何重定位?
1、链接脚本指定链接地址
2、判断运行地址和链接地址是否相同
3、复制代码到指定的链接地址处,使用长转移指令进行跳转
具体的实现如下:
【链接脚本代码】
1 SECTIONS
2 {
3 . = 0xd0024000;
4
5 .text : {
6 start.o
7 * (.text)
8 }
9
10 .data : {
11 *(.data)
12 }
13
14 bss_start = .;
15 .bss : {
16 * (.bss)
17 }
18
19 bss_end = .;
20 }
【重定位代码】
adr r0, _start // 短加载,获取_start的运行地址
ldr r1, =_start // 长加载,获取_start的链接地址
ldr r2, =bss_start // 获取bss链接地址,重定位代码的结束地址
cmp r0, r1 // 比较_start的运行地址和链接地址是否相等
beq clean_bss // 相等:不需要重定位;跳转到clean_bss
// 不相等:需要重定位;继续往下执行
// 汇编实现while完成代码赋值到重定位地址
copy_loop:
ldr r3, [r0], #4 // 源
str r3, [r1], #4 // 目的 先把r3中的内容放入r1的指向的地址;
cmp r1, r2 // 然后r1 =r1 + 4
bne copy_loop
关键字:代码 重定位 S5PV210
引用地址:
总结:代码重定位
推荐阅读最新更新时间:2026-03-14 10:31
代码重定位
1 说明 实验平台: JZ2440 CPU: S3C2440 2 S3C2440的启动过程 图1 S3C2440A Memory Map after Reset S3C2440支持从多种存储设备启动:NOR/NAND Flash, EEPROM, 等等。芯片内部有4K SRAM用于启动设备使用。至于,设备最终以哪一种方式启动,通过配置芯片的OM引脚,由芯片内部实现。 摘自《S3C2440A_UserManual_Rev13》: 图2 BANK0 BUS WIDTH 举个例子,当选择以NOR Flash的方式启动时,芯片的0地址(4K地址空间)会直接映射到Nor Flash上,
[单片机]
S3c2440代码重定位详解4---拷贝代码和链接脚本的改进
本节进行拷贝代码的改进和链接脚本的改进。 前面重定位时,需要ldrb命令从的Nor Flash读取1字节数据,再用strb命令将1字节数据写到SDRAM里面 cpy: ldrb r4, /*首先从flash读出一个字节*/ strb r4, /*让后把数据写到SDRAM*/ add r1, r1, #1 add r2, r2, #1 cmp r2, r3 bne cpy JZ2440上的Nor Flash是16位,SDRAM是32位。 假设现在需要复制16byte数据, 采用ldrb命令每次只能加载1byte,因此CPU需要发出16次命令,内存控制器每次收到命令后,访问硬件Nor Flash,
[单片机]
S3c2440代码重定位详解3---链接脚本的解析
链接脚本的语法 SECTIONS { ... secname start BLOCK(align) (NOLOAD) : AT ( ldadr ) { contents } region :phdr =fill ... } 解释: secname :段名 start :起始地址:运行时的地址(runtime addr);重定位地址(relocate addr) AT ( ldadr ) :可有可无(load addr:加载地址) 不写时LoadAddr = runtime addr { contents } 的内容: start.o //内容为start.o文件 *(.text)所有的代码段文件 sta
[单片机]
S3c2440代码重定位详解2---链接脚本的引入与简单测试
前面程序运行,发现从Nand Flash启动和从Nor Flash启动表现是不一样的。 设置成Nand Flash启动没有问题 显示ABCDE… 设置成NOor Flash启动则显示AAA… 这是什么原因呢? Nor启动 Nor Flash就被认为是0地址,g_Char被放在0x700后面。CPU上电后从0地址开始执行,它能读取Nor Flash上的代码,打印出A,当进行g_Char++的时候,写操作操作无效,下次读取的数据仍然是A。 NAND启动 上电后,Nand Flash前4K代码就被自动的复制到SRAM里面,SRAM是CPU认为的0地址。CPU上电后从0地址开始执行,它读取SRAM上的代码,并g
[单片机]
S3C2440 代码重定位实验(三)
代码重定位 我们现在来解决代码重定位实验(一)所引入的代码重定位问题。 对于S3C2440来说: BIN文件小于4KB时: 若是Nand方式启动,则不存在任何问题 若是Nor方式启动,则我们可以只重定位.data段即可 当BIN文件大于4KB时: 若是Nand方式启动,则需要重定位整个程序,包括代码段和数据段 若是以Nor方式启动,则依然只重定位.data段即可 只重定位.data段和清零.bss段 对于重定位.data段的代码,正常情况下应该是使用汇编来编写的,我为了简便起见,使用了C语言来编写。由于此时尚未重定位数据段和清零BSS段,是不应该调用C函数的。但是我保证了这两个函数不访问全局变量,所以只要正确设置了栈指针,调用
[单片机]
s3c2440学习之路-011代码重定位
1 基本原理 承接上1篇博客 s3c2440学习之路-010 sdram, sdram已经初始化完毕,现在可以正式的发挥SDRAM的价值了。(SDRAM 是可以随意读写的,后续的代码都会放到上面来运行) 1.1 程序段的划分 一个程序编译后,会有代码段、数据段、只读数据段、bss段和注释段 这里主要讲一下bss段为什么可以减小bin文件的大小。bbs主要记录未初始化和初始化为0的全局(static 修饰的局部)变量的位置,而不会记录其具体数据,因为这部分的数值会默认设置为0。 这里看2个小程序 test1.c #include stdio.h char a ; int main(int argc, ch
[单片机]
【s3c2440】第三课:代码重定位
什么是重定位 简单来说就是把程序从内存的一个位置复制到另一个位置。 重定位的重要性 若s3c2440使用Nand Flash启动,则CPU会将Nand Flash的前4k拷贝到s3c2440 soc内部的SRAM。如果程序没有重定位代码,则只能运行Nand flash前4k的程序。 若s3c2440使用Nor Flash启动,则CPU无法修改Nor Flash内存中的数据。如果程序没有重定位代码,则会因为无法修改全局变量、静态变量的值导致程序运行出错。 链接脚本 链接脚本的格式如下: SECTIONS { sectname start BLICK(align) (NOLOAD) : AT( ldadr ) {
[单片机]
tiny4412裸机程序——代码重定位
在前面介绍exynos4412芯片启动过程时,我们知道:一上电,exynos4412首先执行固化在iROM中的代码,iROM首先设置程序运行环境(比如关看门狗、关中断、关MMU、设置栈、设置栈、启动PLL等),然后根据OM引脚确定启动设备(NAND Flash/SD卡/其他),把BL1从里面读出存入iRAM的0x02021400地址处,然后开始启动BL1;BL1从SD卡适当的位置读入14K字节的数据,存在iRAM地址0x02023400处,所以BL2不能大于(14K–4) 字节,这里引出了为什么写这一节的原因:如果我们的程序很大,大于14K怎么办? 运行地址和链接地址: 运行地址是程序当前所处的地址,即程序在运行时,所处的
[单片机]