- 重定位的实质就是:移动数据(数据拷贝)- 把代码段、只读数据段、数据段,移动到它的链接地址处。也就是复制!
 
- 拷贝数据怎么知道源、目的、长度?- 在GCC中,使用链接脚本来描述。
- 在keil中,跟链接脚本对应的是散列文件,散列的意思就是”分散排列“(代码段和数据段分开存储)
 
- 在STM32F103这类资源紧缺的单片机芯片中:- 代码段保存在Flash上,直接在Flash上运行(当然也可以重定位到内存里)
- 数据段保存在Flash上,使用前被复制到内存里
 
 
- 代码段保存在Flash上,直接在Flash上运行(当然也可以重定位到内存里)
- 在资源丰富的MPU板子上:- 内存很大,几十M、几百M,甚至几G
- 可能没有XIP设备(XIP: eXecute In Place,原地执行)- 没有类似STM32F103上的Flash,代码无法在存储芯片上直接运行
 
- 没有类似STM32F103上的Flash,代码无法在存储芯片上直接运行
- 基于这些特点,在MPU板子上- 代码段、数据段、BSS段等等,运行时没有必要分开存放
- 重定位时,把整个程序(包括代码段、数据段等),一起复制到它的链接地址去
 
- 代码段、数据段、BSS段等等,运行时没有必要分开存放
 
- 内存很大,几十M、几百M,甚至几G
- 链接脚本示例 - /* 一个链接脚本可以由多个SECTION来组成, 示例中有4个section: .text .rodata .data .bss */
- SECTIONS {
- /* . : 表示当前地址; 指定当前地址为0xc0200000 */
- /* 程序运行时应该位于这个链接地址上 */
- . = 0xC0200000; /* 对于STM32MP157设置链接地址为0xC0200000, 对于IMX6ULL设为0x80200000 */
- . = ALIGN(4); // 当前地址向4取整
- .text : // .text : 段名; 存放所有文件的代码段
- {
- *(.text) // * : 表示所有文件; 放所有文件的代码段(从所有的.o文件中抽出代码段放在一起)
- }
- . = ALIGN(4);
- .rodata : { *(.rodata) }
- . = ALIGN(4);
- .data : { *(.data) }
- . = ALIGN(4);
- // 链接脚本中想得到更多的信息(地址信息), 可以添加一些符号使其等于当前地址
- // . 表示当前地址, 当前地址可读可写
- __bss_start = .;
- .bss : { *(.bss) *(.COMMON) } // .bss段将所有文件的.bss段和.COMMON段存放在一起
- __bss_end = .;
- }
 
- 链接脚本语法 - 一个链接脚本由一个SECTIONS组成。一个SECTIONS里面,含有一个或多个section - SECTIONS {
- ...
- secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
- { contents } >region :phdr =fill
- ...
- }
 
- section是链接脚本的核心 
- secname:段名
- start:段的起始地址,不写时为当前地址
- BLOCK(align): 指定如何对齐
- AT ( ldadr ): 加载地址,一般不需要写,不写时加载地址就等于该段的起始地址(链接地址)
- contents: 段的内容
- (NOLOAD) 和 >region :phdr =fill暂时用不到,可以先不管
 
 
                         
                                

