定位符号‘.’的使用
‘.’表示当前地址,它可以被赋值也可以赋值给某个变量。
如下为将当前地址赋值给某个变量(链接器链接是按照SECTIONS里的段顺序排列的,前面的排列完之后就能计算出当前地址)
RAM_START = .;
如下为将段存放在特定的地址中:
SECTIONS { . = 0×10000; .text : { *(.text) } . = 0×8000000; .data : { *(.data) } }
“. = 0×10000;”该语句表示将当前地址设置为0x10000。如上代码中,意思是将所有目标文件的text段从0x10000地址开始存放。
end
. = ALIGN(4); __bss_start = .; //把__bss_start赋值为当前位置,即bss段的开始位置 .bss : { *(.bss) } //指定bss段,这里NOLOAD的意思是这段不需装载,仅在执行域中才会有这段 _end = .; //把_end赋值为当前位置,即bss段的结束位置
PROVIDE关键字:
该关键字定义一个(目标文件内被引用但没定义)符号。相当于定义一个全局变量的符号表,其他C文件可以通过该符号来操作对应的存储内存。
SECTIONS { .text : { *(.text) _etext = .; PROVIDE(etext = .); } }
如上,在链接脚本中声明了_etext 符号。特别注意的是_etext 只是一个符号,没有存储内存,并不是一个变量,该符对应(映射)的是一个地址,,其地址为.text section之后的第一个字节的地址。C文件中引用用法如下。
int main() { //引用该变量 extern char _etext; char *p = &_etext; //... }
若在链接脚本中 " _etext = 0x100; ",即表示符号_etext对应的地址为0X100, 此时 & _etext的值为 0x100, char a= *p;表示为 从0X100地址取值存储的值赋值给变量a。
AT>FLASH
AT(ldadr):定义本段存储(加载)的地址,如果不使用这个选项,则加载地址等于运行地址,通过这个选项可以控制各段分别保存于输出文件中不同的位置。
SECTIONS { first 0x00000000 : { head.o init.o } second 0x30000000 : AT(4096) { main.o } }
以上,
head.o放在0x00000000地址开始处,init.o放在head.o后面,他们的运行地址也是0x00000000,即存储和运行地址相同(没有AT指定);
main.o放在4096(0x1000,是AT指定的,存储地址)开始处,但它的运行地址在0x30000000,运行之前需要从0x1000(加载地址处)复制到0x30000000(运行地址处),此过程也就需要读取flash,把程序拷贝到相应位置才能运行。这就是存储地址和运行地址的不同,称为加载时域和运行时域,可以在.lds连接脚本文件中分别指定。