总结:代码重定位

什么是重定位?为什么要代码重定位?

要弄清楚上面的这两个问题,首先要理解下面这几个概念

一、编码

(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
时间: 2024-10-19 07:30:44

总结:代码重定位的相关文章

s3c6410_uboot中的代码重定位(nand->sdram)

本文仅探讨s3c6410从nand flash启动u-boot时的代码重定位过程 参考: 1)<USER'S MANUAL-S3C6410X>第二章 MEMORY MAP 第八章 NAND FLASH CONTROLLER 2)u-boot源码: u-boot-x.x.x/board/samsumg/smdk6410/lowlevel_init.S u-boot-x.x.x/cpu/s3c64xx/start.S u-boot-x.x.x/cpu/s3c64xx/nand_cp.c 代码重定位

s3c2440裸机-代码重定位(2.编程实现代码重定位)

代码重定位(2.编程实现代码重定位) 1.引入链接脚本 我们上一节讲述了为什么要重定位代码,那么怎么去重定位代码呢? 上一节我们发现"arm-linux-ld -Ttext 0 -Tdata 0x30000000"这种方式编译出来的bin文件有800多M,这肯定是不行的,那么需要怎么把.data段重定位到sdram呢? 可以通过AT参数指定.data段在编译时的存放位置,我们发现这样指定太不方便了,而且不好确定要放在bin文件的哪个位置.这里就要引入链接脚本,它可以帮我们解决这个不必要

代码重定位和位置无关码

通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位. 现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简单地内存访问,通常我们使用sdram这个介质作为程序运行的载体.但是只重定位data段这种方式存在弊端.第一,我们的调试工具通常不支持这种分体形式(比如我们的之前的代码在0地址开始存放text和rodata段,而在间隔很远处sdram 0x30000000存放data段,这就是分体的形式)的代码:第

s3c2440代码重定位和段的引入——学以致用,综合Makefile的锻炼

对于2440而言,nand启动,nand的前4k内容由硬件复制到sram. nor flash,可以像内存一样读,但是不能像内存一样写,执行写操作需要特殊的操作. 程序中包含有需要写的全局或者静态变量,它们在bin文件中,写在nor flash上,直接修改这样的变量是无效的. 到底什么意思呢?还是看例子比较有说服力. 在学习C语言的过程中,我们或多或少知道一些东西,c/c++可执行文件需要预处理,编译,汇编,连接. 程序有text段,data段,bss段,rodata段等等,今天,就和它们来个亲

代码重定位

局部变量存储在栈上,栈指向SDRAM可读可写 全局变量包含在.bin文件中,烧写在nor文件中 静态变量 nor_flash不能直接的写 程序中至少包含有代码段和数据段(rodata .bss(初值为0,无初值的全局变量).common注释) const char g_char2 = 'B'   //const是固定的,只能读不能改 rodata 只读数据段 原文地址:https://www.cnblogs.com/rose-/p/12630595.html

重定位与链接脚本

1.为什么需要重定位 位置无关编码(PIC,position independent code):汇编源文件被编码成二进制可执行程序时编码方式与位置(内存地址)无关. 位置有关编码:汇编源码编码成二进制可执行程序后和内存地址是有关的. 我们在设计一个程序时,会给这个程序指定一个运行地址(链接地址).就是说我们在编译程序时其实心里是知道我们程序将来被运行时的地址(运行地址)的,而且必须给编译器链接器指定这个地址(链接地址)才行.最后得到的二进制程序理论上是和你指定的运行地址有关的,将来这个程序被执

SDRAM和重定位(四)---链接地址和运行地址

在了解重定位之前,必须先区分开链接地址和运行地址,位置有关代码和位置无关代码 ========================================================= 链接地址和运行地址: 链接地址:指在链接时指定的地址,是我们设想的将来程序要运行的地址.程序中所有标号的地址在链接后便确定了,不管程序在哪运行,都不会改变.使用arm-linux-objdump反汇编查看的就是链接地址. 运行地址:指程序在板子中实际运行的地址 从上面的定义可以看出,链接地址和运行地址可以

重定位引入和链接脚本

1.一个事实:大部分指令是位置有关编码位置无关编码(PIC,position independent code):汇编源文件被编码成二进制可执行程序时编码方式与位置(内存地址)无关.位置有关编码:汇编源码编码成二进制可执行程序后和内存地址是有关的. 我们在设计一个程序时,会给这个程序指定一个运行地址(链接地址).就是说我们在编译程序时其实心里是知道我们程序将来被运行时的地址(运行地址)的,而且必须给编译器链接器指定这个地址(链接地址)才行.最后得到的二进制程序理论上是和你指定的运行地址有关的,将

关于重定位代码的浅显理解

首先需要朱有鹏老师,这是在学习了朱老师的课程之后的一点理解,代码是根据朱老师的源码学习之后编写的. 根据反汇编代码  d0024010:     e24f0018       sub      r0, pc, #24 可以看出通过adr汇编伪指令将加载地址写入r0寄存器,此时因为adr指令采用相对寻址的寻址方式所以adr实际写入r0寄存器的地址为程序的加载地址而非反汇编代码所指示的0xd0024000,通过ldr伪指令将所需重定位的地址写入r1寄存器,此时r1所存的地址为0xd0024064,该