连接脚本的解析

上篇随笔写了一个连接脚本,如果你不想看那个复杂的ld连接脚本文章,看我上一篇和这篇随笔就可以做到编写目前我们够用的连接脚本了,本章的知识点全部来自那篇文章。

先看连接脚本的格式:

其中有一些东西我们是不会用到的:

第一个,段名,这个我们可以随便取,但是一般按照.data .text等这样的名字,也可以命名成first,second等这样,这两种命名是连接脚本中最常见的。

start:加载地址。 start可以表示为任何表达式。


BLOCK(align)您可以在该部分开始之前包含BLOCK()指定位置计数器.,以便该部分从指定的对齐位置开始。 align是一个表达式。

这个在我们的连接脚本中不会使用。

(NOLOAD)

该 “(NOLOAD)”指令将标记一个部分在运行时不被加载。链接器将正常处理该部分,但会将其标记为程序加载器不会将其加载到内存中。例如,在下面的脚本示例中,该ROM部分位于内存位置‘0‘在程序运行时不需要加载。该ROM部分的内容将照常显示在链接器输出文件中。

SECTIONS {
  ROM 0(NOLOAD):{...}
  ...
}这个在我们的连接脚本中不会使用。AT ( ldadr )The expression ldadr that follows the AT keyword specifies the load address of the section. The default (if you do not use the AT keyword) is to make the load address the same as the relocation address. This feature is designed to make it easy to build a ROM image. For example, this SECTIONS definition creates two output sections: one called `.text‘, which starts at 0x1000, and one called `.mdata‘, which is loaded at the end of the `.text‘ section even though its relocation address is 0x2000. The symbol _data is defined with the value 0x2000:
SECTIONS
  {
  .text 0x1000 : { *(.text) _etext = . ; }
  .mdata 0x2000 :
    AT ( ADDR(.text) + SIZEOF ( .text ) )
    { _data = . ; *(.data); _edata = . ;  }
  .bss 0x3000 :
    { _bstart = . ;  *(.bss) *(COMMON) ; _bend = . ;}
}
The run-time initialization code (for C programs, usually crt0) for use with a ROM generated this way has to include something like the following, to copy the initialized data from the ROM image to its runtime address:
char *src = _etext;
char *dst = _data;

/* ROM has data at end of text; copy it. */
while (dst < _edata) {
  *dst++ = *src++;
}

/* Zero bss */
for (dst = _bstart; dst< _bend; dst++)
  *dst = 0;
AT就是指定加载地址。>regionAssignthis section to a previously defined region of memory.(这个我们也不会用到)

这个我们也不用到。

所以我们需要掌握的也就那么一点。然后说明一点,上面我们连接脚本中使用了一个LOADADDR函数:LOADADDR(section)Return the absolute load address of the named section. 其实就是返回这个section的加载地址。SIZEOF(section)如果该部分已被分配,则返回指定部分的字节大小
当没有指定AT时,运行地址和加载地址是一样的,而且,在指定了一个运行地址之后,后面再继续指定段,此时没有再指定运行地址时,该段的运行地址时紧接着前一个指定的eg:

.rodata段没有指定运行地址,证明它是紧接着上面的.text段排放的。

上面的图片说明了我们需要用代码实现重定位,在运行地址和加载地址不相同的时候:

这里运行地址是0x30000000,加载地址是0x800,不相等,此刻就需要我们编写重定位代码,这也就是上一篇随笔中的汇编copy的原因。

bss段是存放初始值为0或者没有初始化的全局变量的,它不存放在elf文件也不存放在bin文件,原因很简单,要是有10万个为0的值,难道我们要开辟那么大的空间去存放这些数吗?所以,bss段的清零也需要我们自己做,bss段连接在.data段后面的,这也就是bss段的变量正真存放的位置,这也让我们之后读写bss段的数据也可以有效。有人问,既然bss段不存放在bin文件中,为什么我们还要清零它呢?

第一,bss段决定了它的初始值是0,;

第二,不存放在bin文件中,但它存放在内存中,这里是我们的sdram,不然为什么我们可以对bss段的数据进行算术操作而不出问题呢;

第三,各个变量或者函数是有特定存放段的,这是连接器工作的基础。

下一篇随笔书写bss段清零操作,并且改进我们的重定位代码。

 
时间: 2024-07-30 17:38:47

连接脚本的解析的相关文章

nsis安装包_示例脚本语法解析

以下是代码及解析,其中有底色的部分为脚本内容. 注释.!define.变量.!include.常量 ; Script generated by the HM NIS Edit Script Wizard. ; HM NIS Edit Wizard helper defines !define PRODUCT_NAME "signjing安装示例" !define PRODUCT_VERSION "0.0.0.1" !define PRODUCT_PUBLISHER

SQL Server 连接问题案例解析(1)

SQL Server 连接问题案例解析(1) 转载自:http://blogs.msdn.com/b/apgcdsd/archive/2015/04/27/sql.aspx?CommentPosted=true#commentmessage Microsoft Network Monitor(Netmon)是由微软发布的一款网络协议数据分析工具,利用Netmon可以捕获网络数据并进行查看和分析. 在处理SQL Server 的连接问题时,Netmon常常会起到关键的作用.在本篇博文中,我将为大家

拷贝代码和连接脚本的改进

上一篇随笔说了,需要清除bss段,我们现在定义main函数如下: 注意这个全局变量是没有初始值的,即存放在bss段中,如果我们的启动文件没有清除bss段,串口的输出将是你想不到情况.比如,现在程序运行执行了++操作20次,你下次快速断电再上电的时候,g_Char2的值是接着之前的值增加的,而增加了清除bss段之后,每次重新上电,都是从0开始的.到这里我是觉得纳闷的,我们程序是重定位到了sdram的,既然是ram中,掉电不就应该是马上丢失数据了吗?然后查询了一下资料,发现: 然后我就多等了一些时间

C语言引用连接脚本lds中的符号——清除bss段,c实现方式

之前我们的启动文件清除bss和拷贝都是通过汇编的方式的实现,但是,我们能够使用C语言,就不使用汇编: 先看连接脚本: SECTIONS { . = 0x30000000; __code_start = .; . = ALIGN(4); .text : { *(.text) } . = ALIGN(4); .rodata : { *(.rodata) } . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); __bss_start = .; .bss :

Python操作小结(连接mysql、解析txt文件)

有段时间没有使用python了,对它的语法有点生疏,花了几个小时熟悉,期间发现很多小细节不清楚.为了下次能快速上手,避免重复犯错,我将python使用过程中的一些问题在这篇博文中记录小结一下,主要内容涉及到python操作mysql数据库,和解析txt文本.注:我用的是python2.7版本. 一.导入模块 python的脚本文件里面,可以导入其他脚本文件,并引用其中的方法和参数,使用关键字import.如下: import os,glob,sys 二.基础语法 1.普通变量定义 python

【javascript】javascript学习之js脚本的解析步骤

将javascript代码加入到HTML代码中,即使用<script>标签的方式有两种:直接嵌入页面中和使用外部js文件. 使用<script>标签嵌入html代码中时,需要指定其类型:type="text/javascript".不过在html5标准中<script>标签的type默认为"text/javascript",可以省略不写,不过考虑到低版本的兼容问题,一般还是加上比较好. 嵌入式js代码: 添加到<script

转:Ogre源代码浅析——脚本及其解析(一)

Ogre的许多外部资源数据都有着相应的脚本格式,现例举如下: Material(材质):Ogre使用的是“大材质”的概念.狭义的“材质”概念往往是与“贴图”等概念区分开的,比如在Lambert光照模型中,它一般用来指物体表面对模拟光的环境分量.漫反射分量和镜面反射分量的作用的响应属性.而在Ogre中,“材质”既包括了上述狭义的材质含义,又包括对要使用的贴图的描述,还可以包括要使用的shader的相关信息.这些都是用Ogre的材质脚本来描述的.其实仔细思考一下就会发现,Ogre对材质概念的定义是恰

VBA中使用JavaScript脚本语言解析JSON数据

JSON:JavaScript 对象表示法(JavaScript Object Notation) 和xml相似,都是文本形式(保存在文本文件中或字符串等形式),比如: jsstr = {"系别":"历史系","班级":"一班", "学员":[ {"姓名":"张三","年龄":25,"性别":"男"}, {&

PHP脚本预解析

动态php缓存知识####################################################php预解析存在共享内存中,开启opcache.php5.5以上配置模块即可php.ini: [opcache] ; 启动操作码缓存 opcache.enable=1 ; 针对支持CLI版本PHP启动操作码缓存 一般被用来测试和调试 opcache.enable_cli=1 ; 共享内存大小,单位为MB opcache.memory_consumption=128 ; 存储临