本文由Jacky原创,来自http://blog.chinaunix.net/u1/58780/showart.php?id=462971
对于 .lds 文件,它定义了整个程序编译之后的连接过程,决定了一个可执行程序的各个段的存储位置。虽然现在我还没怎么用它,但感觉还是挺重要的,有必要了解一下。
先看一下GNU官方网站上 对 .lds 文件形式的完整描述:
2 、 contents :决定哪些内容放在本段,可以是整个目标文件,也可以是目标文件中的某段(代码段、数据段等)
3 、 start :本段连接(运行)的地址,如果没有使用 AT ( ldadr ),本段存储的地址也是 start 。 GNU 网站上说 start 可以用任意一种描述地址的符号来描述。
4 、 AT ( ldadr ):定义本段存储(加载)的地址。
看一个简单的例子:(摘自《 2410 完全开发》)
以上,
head.o
放在
0x00000000
地址开始处,
init.o
放在
head.o
后面,他们的运行地址也是
0x00000000
,即连接和存储地址相同(没有
AT
指定);
main.o
放在
4096
(
0x1000
,是
AT
指定的,存储地址)开始处,但是它的运行地址在
0x30000000
,运行之前需要从
0x1000
(加载处)复制到
0x30000000
(运行处),此过程也就用到了读取
Nand flash
。
这就是存储地址和连接(运行)地址的不同,称为加载时域和运行时域,可以在 .lds 连接脚本文件中分别指定。
编写好的 .lds 文件,在用 arm-linux-ld 连接命令时带 -Tfilename 来调用执行,如
arm-linux-ld – Tnand.lds x.o y.o – o xy.o 。也用 -Ttext 参数直接指定连接地址,如
arm-linux-ld – Ttext 0x30000000 x.o y.o – o xy.o 。
既然程序有了两种地址,就涉及到一些跳转指令的区别,这里正好写下来,以后万一忘记了也可查看,以前不少东西没记下来现在忘得差不多了。。。
ARM 汇编中,常有两种跳转方法: b 跳转指令、 ldr 指令向 PC 赋值。
我自己经过归纳如下:
(1)
b step1 : b 跳转指令是相对跳转,依赖当前 PC 的值,偏移量是通过该指令本身的 bit[23:0] 算出来的,这使得使用 b 指令的程序不依赖于要跳到的代码的位置,只看指令本身。
(2)
ldr pc, =step1 :该指令是从内存中的某个位置( step1 )读出数据并赋给 PC ,同样依赖当前 PC 的值,但是偏移量是那个位置( step1 )的连接地址(运行时的地址),所以可以用它实现从 Flash 到 RAM 的程序跳转。
(3)
此外,有必要回味一下 adr 伪指令, U-boot 中那段 relocate 代码就是通过 adr 实现当前程序是在 RAM 中还是 flash 中。仍然用我当时的注释:
下面,结合
u-boot.lds
看看一个正式的连接脚本文件。这个文件的基本功能还能看明白,虽然上面分析了好多,但其中那些
GNU
风格的符号还是着实让我感到迷惑,好菜啊,怪不得连被
3
家公司鄙视,自己鄙视自己。。。
对于 .lds 文件,它定义了整个程序编译之后的连接过程,决定了一个可执行程序的各个段的存储位置。虽然现在我还没怎么用它,但感觉还是挺重要的,有必要了解一下。
先看一下GNU官方网站上 对 .lds 文件形式的完整描述:
secname 和 contents 是必须的,其他的都是可选的。下面挑几个常用的看看: 1 、 secname :段名
2 、 contents :决定哪些内容放在本段,可以是整个目标文件,也可以是目标文件中的某段(代码段、数据段等)
3 、 start :本段连接(运行)的地址,如果没有使用 AT ( ldadr ),本段存储的地址也是 start 。 GNU 网站上说 start 可以用任意一种描述地址的符号来描述。
4 、 AT ( ldadr ):定义本段存储(加载)的地址。
看一个简单的例子:(摘自《 2410 完全开发》)
这就是存储地址和连接(运行)地址的不同,称为加载时域和运行时域,可以在 .lds 连接脚本文件中分别指定。
编写好的 .lds 文件,在用 arm-linux-ld 连接命令时带 -Tfilename 来调用执行,如
arm-linux-ld – Tnand.lds x.o y.o – o xy.o 。也用 -Ttext 参数直接指定连接地址,如
arm-linux-ld – Ttext 0x30000000 x.o y.o – o xy.o 。
既然程序有了两种地址,就涉及到一些跳转指令的区别,这里正好写下来,以后万一忘记了也可查看,以前不少东西没记下来现在忘得差不多了。。。
ARM 汇编中,常有两种跳转方法: b 跳转指令、 ldr 指令向 PC 赋值。
我自己经过归纳如下:
(1)
b step1 : b 跳转指令是相对跳转,依赖当前 PC 的值,偏移量是通过该指令本身的 bit[23:0] 算出来的,这使得使用 b 指令的程序不依赖于要跳到的代码的位置,只看指令本身。
(2)
ldr pc, =step1 :该指令是从内存中的某个位置( step1 )读出数据并赋给 PC ,同样依赖当前 PC 的值,但是偏移量是那个位置( step1 )的连接地址(运行时的地址),所以可以用它实现从 Flash 到 RAM 的程序跳转。
(3)
此外,有必要回味一下 adr 伪指令, U-boot 中那段 relocate 代码就是通过 adr 实现当前程序是在 RAM 中还是 flash 中。仍然用我当时的注释: