代码重定位和位置无关码

通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位。

现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简单地内存访问,通常我们使用sdram这个介质作为程序运行的载体。但是只重定位data段这种方式存在弊端。第一,我们的调试工具通常不支持这种分体形式(比如我们的之前的代码在0地址开始存放text和rodata段,而在间隔很远处sdram 0x30000000存放data段,这就是分体的形式)的代码;第二,这种分体方式需要能够直接运行程序的flash比如nor flash才可以工作,但是有些板子根本连nor flash都没有,那么只能通过第二种方式进行开发了。

第二种方式是把整个程序都复制到内存(sdram),这种方式所有数据都是紧挨着的,以后我们都使用这种方式。

现在思考一个问题,关于第二种方式,我们的bin文件是由连接脚本指定了运行地址为sdram(0x30000000)的,但是这个bin文件我们烧写在nor flash,是从0地址开始运行的,那么在nor flash上的代码就需要把整个bin文件拷贝到sdram中去,这就是重定位,但这就要求我们必须做到,在重定位之前的代码必须是位置无关码。(连接脚本指定我们程序的运行地址为0x30000000,为什么我们的在nor flash上的代码从0地址开始运行也能工作?这就是建立在我们这部分代码必须是位置无关码的基础上的,0地址处运行和0x30000000处运行达到同样效果,需要我们保证,在重定位之前,也就是复制操作没有完成之前的代码,必须是位置无关的,重定位之后,就没有限制了,可以位置有关,也可以位置无关)。

现在修改我们之前的连接脚本和启动文件:

SECTIONS
{
    . = 0x30000000;

    . = ALIGN(4);
    .text      :
    {
      *(.text)
    }

    . = ALIGN(4);
    .rodata : { *(.rodata) }

    . = ALIGN(4);
    .data : { *(.data) }

    . = ALIGN(4);
    __bss_start = .;
    .bss : { *(.bss) *(.COMMON) }
    _end = .;
}

上面是连接脚本,我想此时应该都不需要备注了吧,基本语法。表示0x30000000处是我们的运行地址。

未完待续。。。

时间: 2024-10-01 03:04:59

代码重定位和位置无关码的相关文章

总结:代码重定位

什么是重定位?为什么要代码重定位? 要弄清楚上面的这两个问题,首先要理解下面这几个概念 一.编码 (1)位置无关编码:PIC,可执行程序运行时与代码在内存中的地址无关,代码中没有使用绝对地址,而是使用的相对地址.(例如:B.BL.MOV等指令) (2)位置有关编码:可执行程序运行时与代码在内存中的地址有关系.(例如:LDR PC, =MAIN等指令) 二.地址 (1)链接地址:程序编译链接时指定的地址(使用makefile或者链接脚本可以指定链接地址) (2)运行地址:程序在内存中实际运行的地址

位置无关码

ARM下的位置无关和相关码 为什么需要位置无关码? 见 : U-BOOT详解(什么是<编译地址>?什么是<运行地址>?)  http://bbs.21ic.com/forum.php?mod=viewthread&tid=857037&typeid=114       ARM位置无关代码设计规范  http://wenku.baidu.com/view/5ef25b890b4c2e3f562763a8.html 位置无关可执行文件PIE包括位置无关代码PIC和位置无

s3c6410_uboot中的代码重定位(nand-&gt;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 代码重定位

位置无关码(BL)与绝对位置码(LDR)

BL :带连接分支跳转指令,也是位置无关码(相对位置),一般用于带返回的子程序跳转,B指令是用于无返回的跳转. LDR:通常都是作加载指令的,但是它也可以作伪指令,通常有两种不同的表示:  1)LDR pc, =MyHandleIRQ 表示将MyHandleIRQ地址放入pc寄存器中,相当于PC=MyHandleIRQ . 2)LDR PC,MyHandleIRQ 表示将 MyHandleIRQ地址中的值放入pc寄存器中,类似于C语言中的指针形式,相当于PC=*(MyHandleIRQ ). 实

位置无关码 位置相关码

在汇编中  使用位置无关码 b,bl 在c语言中 使用位置无关码 不用全局变量  不用静态变量 位置无关码:CPU取指时,总是相对于本条执行指令的相对地址去取指.比如指行一个ADD指令时,PC要取下一指令的地址,就在原来的基础上+4.这就不管你代码放在存储器的任何位置,只要他们的相对地址没有改变,就能正常执行程序.一般上电复位那几条语句就必须是位置无关码指令. 位置相关码:可以这样来说,就是CPU每次取指都从绝对位置去取,而不是上面的相对位置.这个绝对地址就是相对起始地址0来说的.这样,就要求你

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

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

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

共享库中的位置无关代码(PIC)

原作者:Eli Bendersky http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/ 在之前的文章里我已经描述过在将共享库载入程序地址空间时需要特殊的处理.简而言之,在链接器创建共享库时,它不能预先知道这个库将在哪里载入.这给在库里访问数据与代码带来了麻烦,应该使得这些访问指向正确的内存位置. 在Linux ELF共享库里解决这个问题有两个主要途径: 1.