跟我一起学RT-Thread之重定位

1.概念

重定位就是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程。这句话的意思就是:使逻辑地址与实际物理地址一一对应的过程

程序的逻辑地址就是链接地址,由于程序的下载地址不一定是逻辑地址,所以将程序重新定位(拷贝)到逻辑地址所对应的物理地址处就叫做重定位,这是一个过程。

2.程序中含有什么

  • 代码段:如果它不在链接地址上,就需要重定位
  • 只读数据段:如果它不在链接地址上,就需要重定位
  • 可读可写的数据段:如果它不在链接地址上,就需要重定位
  • BSS段:不需要重定位,因为程序里根本不保存BSS段,使用前把BSS段对应的空间清零即可

3.谁来做重定位

  • 程序本身:它把自己复制到链接地址
  • 一开始,程序可能并不位于它的链接地址上,为什么它可以执行重定位的操作?
    • 因为重定位的代码是使用“位置无关码”写的
  • 位置无关码:这段代码扔在任何位置都可以运行,跟它所在的位置无关
  • 怎么写出位置无关码:
    • 跳转:使用相对跳转指令,不能使用绝对跳转指令
      • 只能使用branch指令(比如bl main),不能给PC直接复制,比如ldr pc, =main
    • 不要访问全局变量、静态变量
    • 不使用字符串

4.重定位和清除BSS段

4.1. 重定位

  • 核心:拷贝
  • 拷贝的三要素:源、目的、长度
    • 怎么知道代码段/数据段保存在哪?(加载地址)
    • 怎么知道代码段/数据段要被复制到哪?(链接地址)
    • 怎么知道代码段/数据段的长度?

这一切

  • 在keil中使用散列文件(Scatter File)来描述
  • 在GCC中使用链接脚本(Link Script)来描述

重定位,最重要的就是拷贝,注意是拷贝,也就是复制一份。

4.2.清除BSS段

  • 核心:清零
  • 清零的三要素:目的、值、长度

这一切

  • 在keil中使用散列文件(Scatter File)来描述
  • 在GCC中使用链接脚本(Link Script)来描述

5.重定位的本质

把代码段、只读数据段、数据段,移动到它的链接地址处。
也就是复制

数据复制的三要素:源、目的、长度。

  • 数据保存在哪里?加载地址

  • 数据要复制到哪里?链接地址

  • 长度

这3要素怎么得到?
在GCC中,使用链接脚本来描述。
在keil中,跟链接脚本对应的是散列文件,散列的意思就是"分散排列"。

在STM32F103这类资源紧缺的MCU单片机芯片中:

  • 代码段保存在Flash上,直接在Flash上运行(当然也可以重定位到内存里)
  • 数据段保存在Flash上,使用前被复制到内存里

但是,在资源丰富的MPU板子上:

  • 内存很大,几十M、几百M,甚至几G

  • 可能没有XIP设备(XIP: eXecute In Place,原地执行)

    • 没有类似STM32F103上的Flash,代码无法在存储芯片上直接运行
  • 基于这些特点,在MPU板子上

    • 代码段、数据段、BSS段等等,运行时没有必要分开存放
    • 重定位时,把整个程序(包括代码段、数据段等),一起复制到它的链接地址

猜你喜欢

转载自blog.csdn.net/qq_46359697/article/details/113801634