运行地址、链接地址、加载地址、存储地址

1、概念理解

运行地址<—>链接地址:他们两个是等价的,只是两种不同的说法。

加载地址<—>存储地址:他们两个是等价的,也是两种不同的说法。

运行地址:程序在SRAM、SDRAM中执行时的地址。就是执行这条指令时,PC应该等于这个地址,换句话说,PC等于这个地址时,这条指令应该保存在这个地址内。

加载地址:程序保存在Nand flash中的地址

位置无关码:B、BL、MOV都是位置位置无关码。

位置有关码:LDR PC,=LABEL等类似的代码都是位置有关码。

2、链接脚本格式

<SECTIONS>基本命令
SECTIONS 描述输出文件的映射图 -> 输出文件各段、各文件怎么放置
一个SECTIONS命令内部包含一个或多个段,段是连接脚本的基本单元,它 表示输入文件某部分怎么放置;

格式:
SECTIONS{
 
secname start ALIGN(align)(NOLOAD):AT(ldadr)
{contents}>region:phdr=fill
}
secname:命名这个段   
contents:用来确定代码的什么部分放在这个段
start:是这个段的重定位地址,也叫运行地址。如果代码中有位置无关的 指令,程序在运行时必须放在这个地址上。
ALIGN(align):虽然指定了运行地址,但仍可以使用ALIGN(align)来指定 对齐的要求—这个对齐的地址才是真正的地址
(NOLOAD):来告诉加载器,在运行时不用加载这个段
AT(ldadr):指定这个段在编译出来的映像文件中的地址——加载地址

3、链接脚本分析

先看一个链接脚本:

SECTIONS{

 first 0x00000000 : {head.o init.o}

 second 0xB0004000 : AT(2048){leds.o}

}

链接脚本将程序分为两个段:first和second。前者由head.o和init.o组成,它的加载地址运行地址都是0,所以在运行时不需要移动代码,后者由leds.o组成,它的加载地址为2048,重定位地址为0xB0004000,这表明段second存放在编译所得的映像文件的2048处,在运行前需要将它复制到地址0xB0004000(MMU映射),将编译所得的映像文件烧入到nand flash后,head.o和init.o依次从0x00000000处存放,而leds.o存放在2048处。从nand flash启动时,cpu首先将nand flash的前4KB复制到cpu自身的ram(steppingstone)中去,这样leds.o存放在地址为2048处,而运行的时候需要将steppingstone中2048 - 4096的内容复制到sdram中起始地址0xB0004000处,从而使用ldr跳转时才会正确执行下去。

4、假若程序不位于链接地址时程序会出现什么问题

访问某些全局变量时就会出错,因为访问这些全局变量时用的是它的链接地址,我去链接地址访问你,你就必须位于链接地址上。如下图,程序应该位于SDRAM上的某个地方,但是一上电是从2440的片内4K RAM 的0地址开始执行的,为什么从0地址执行的一小段代码能够正确运行,这一小段代码用到位置无关码写。




1、概念理解

运行地址<—>链接地址:他们两个是等价的,只是两种不同的说法。

加载地址<—>存储地址:他们两个是等价的,也是两种不同的说法。

运行地址:程序在SRAM、SDRAM中执行时的地址。就是执行这条指令时,PC应该等于这个地址,换句话说,PC等于这个地址时,这条指令应该保存在这个地址内。

加载地址:程序保存在Nand flash中的地址

位置无关码:B、BL、MOV都是位置位置无关码。

位置有关码:LDR PC,=LABEL等类似的代码都是位置有关码。

2、链接脚本格式

<SECTIONS>基本命令
SECTIONS 描述输出文件的映射图 -> 输出文件各段、各文件怎么放置
一个SECTIONS命令内部包含一个或多个段,段是连接脚本的基本单元,它 表示输入文件某部分怎么放置;

格式:
SECTIONS{
 
secname start ALIGN(align)(NOLOAD):AT(ldadr)
{contents}>region:phdr=fill
}
secname:命名这个段   
contents:用来确定代码的什么部分放在这个段
start:是这个段的重定位地址,也叫运行地址。如果代码中有位置无关的 指令,程序在运行时必须放在这个地址上。
ALIGN(align):虽然指定了运行地址,但仍可以使用ALIGN(align)来指定 对齐的要求—这个对齐的地址才是真正的地址
(NOLOAD):来告诉加载器,在运行时不用加载这个段
AT(ldadr):指定这个段在编译出来的映像文件中的地址——加载地址

3、链接脚本分析

先看一个链接脚本:

SECTIONS{

 first 0x00000000 : {head.o init.o}

 second 0xB0004000 : AT(2048){leds.o}

}

链接脚本将程序分为两个段:first和second。前者由head.o和init.o组成,它的加载地址运行地址都是0,所以在运行时不需要移动代码,后者由leds.o组成,它的加载地址为2048,重定位地址为0xB0004000,这表明段second存放在编译所得的映像文件的2048处,在运行前需要将它复制到地址0xB0004000(MMU映射),将编译所得的映像文件烧入到nand flash后,head.o和init.o依次从0x00000000处存放,而leds.o存放在2048处。从nand flash启动时,cpu首先将nand flash的前4KB复制到cpu自身的ram(steppingstone)中去,这样leds.o存放在地址为2048处,而运行的时候需要将steppingstone中2048 - 4096的内容复制到sdram中起始地址0xB0004000处,从而使用ldr跳转时才会正确执行下去。

4、假若程序不位于链接地址时程序会出现什么问题

访问某些全局变量时就会出错,因为访问这些全局变量时用的是它的链接地址,我去链接地址访问你,你就必须位于链接地址上。如下图,程序应该位于SDRAM上的某个地方,但是一上电是从2440的片内4K RAM 的0地址开始执行的,为什么从0地址执行的一小段代码能够正确运行,这一小段代码用到位置无关码写。




猜你喜欢

转载自blog.csdn.net/Meteor_s/article/details/81665733
今日推荐