重定位的理解

一 、代码的组成

程序至少包含:代码段+数据段

代码段:.text

数据段:一般的全局变量,初值不为0的经过初始化的全局变量

        如:char g_char ='A';    //初值为A的字符型全局变量

rodata:const的全局变量,只读数据段

bss:初值为0,或者没有初值的全局变量,不保存在bin文件中

     如:int g_A =0;     //初值为0的整形全局变量

           int g_B;         //无初值的整形全局变量

commen:注释,不保存在bin文件中

关于bss段和comment段为什么不保存在bin文件中,可以这样来理解,如果我们的代码中有非常多的全局变量(比如100万个char型变量),如果这些数据都保存在bin文件中,那么我们的bin文件得有多大,显然这是不可能的。

所以,一般地,在链接脚本中,我们都需要指出这几个段在内存中的分配情况。如下所示:

                                               

二、必须知道的几个概念

1、链接地址和运行地址。

①运行地址,顾名思义就是程序运行的时候的地址,也就是你用工具将代码下载到RAM的那个地址,也叫加载地址。

②链接地址,由链接脚本指定的地址。为什么需要链接脚本指定地址呢?你想一下,在c语言编程中,当我们需要调用一个A函数的时候,编译器是怎么找到这个A函数?编译器肯定是知道它被放在哪里才可以找到它。那就是链接脚本的作用,链接脚本其实在程序被执行之前都已经指定A函数一个地址编号,以后所有的函数调用我们都会去这个地址编号那里寻找A函数。有点类似于c语言的指针变量。

2、什么是重定位?

重定位就是代码搬移到你想要的地址,本来程序是运行在运行地址处的,

你可以通过重定位搬移到链接地址处。

3、为什么需要重定位?

大部分的程序是不需要重定位的,但是有时候需要进行重定位,最常见的例子就是

我们的UBOOT,因为我们的UBOOT有200多KB,但是我们开始BL0的地方只有96KB。

所以我们需要在96KB之前进行重定位,使开发板能够进行重定位。

三、重定位之前的状态

重定位决定了pc取指令的地址,但是很显然SoC芯片刚刚上电时,重定位还没有实现,SoC需要执行一段代码来实现重定位,所以这时PC指针并没有指向重定位地址的地方,那么这个过程是如何实现的呢?

 上电后,PC指向哪里?

对于任何一种SoC芯片来说,上电后PC指针的位置是有硬件设计决定的,一般地,对于cortex-M系列内核的芯片,上电后PC指针都为0,指向0地址处。

对于nand启动,0地址对应片内sram,因为nand控制器上电后自动将nand中的前4k大小拷贝到了sram中,所以此时sram中存在代码(即nand中前4K代码),内核就可以取指令并执行了。

对于nor启动,0地址对应nor芯片,我们已经将程序下载到nor上了,所以此时pc也可以取指令并执行了。


猜你喜欢

转载自blog.csdn.net/qq_39541098/article/details/80997867