链接脚本的改进


本文是基于韦东山视频的学习笔记

汇总点这

链接脚本的简单解析和bss段的清零

连接脚本的简单解析

链接文件的详细描述文档

根据文档的描述,这里是完整的语法。

Here is the full syntax of a section definition, including all the optional portions:
SECTIONS {

secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{ contents } >region :phdr =fill

}

但是目前来说,我们只用到

SECTIONS {
secname start : AT ( ldadr )
{ contents }
}

  • secname : 段名
  • start:运行地址
  • ldadr: 加载地址 ,不写时,默认等于运行地址
  • contents:内容

bss

在前面的博客有说bss段的数据一般不烧进 bin 文件,因为里面都是一些初始值为零或没有初始值的全局变量,但是当真的需要这些初始值为零的变量怎么办咧,那我们就得来把bss段清零。

bss段代码

	/*bss段清零*/
	ldr r1, =bss_start
	ldr r2, =bss_end
	mov r3, #0
clean_bss:
	strb r3, [r1]
	add r1, r1, #1
	cmp r1, r2
	bne clean_bss

链接文件代码

SECTIONS {
.text 	0: {*(.text)}	
.rodata  : {*(.rodata)}	
.data	0x30000000: AT(0x800) 
{	
	data_load_addr = LOADADDR(.data);
	data_start = .;
	*(.data)
	data_end = .;
}

.bss 	 : 
{	
	bss_start = .;
	*(.bss) *(.COMMET)
	bss_end = .;
}

}

链接脚本的简单改进

原因

上文重定位的代码和 bss 段的清零中,汇编代码用的是

mov r0, #0x800
ldrb r1, [r0]
mov r0, #0x30000000
strb r1, [r0]

copy:
ldrb r0, [r1]
strb r0, [r2]
add r1, r1, #1
add r2, r2, #1
cmp r2, r3
bne copy

但是,用 ldrb 和 strb 的效率实在时太慢了。举个栗子。

  • 如果需要重定位16字节的数据,用 ldrb 去访问16位的 Nor flash 的话,我们就需要访问16次,再用 strb 去写入32位 sdram 需要写入16次,一共32次。
  • 但是相同的情况下,要重定位16字节的数据,如果用 ldb 去访问 Nor flash 的话,就只需要访问8次,如果用 str 去写 sdram 的话,就只需要写入 4 次,一共12次。

不难看出,第二种方法更加有效率,当数据成千上百万计的时候,将会有巨大的差别。

代码

copy:	
	ldr r4, [r1] 
	str r4, [r2]
	add r1, r1, #4
	add r2, r2, #4
	cmp r2, r3
	ble  copy	;改为小于等于,因为现在是复制4字节
	
	/*bss段清零*/
	ldr r1, =bss_start
	ldr r2, =bss_end
	mov r3, #0
clean_bss:
	str r3, [r1]
	add r1, r1, #4 	;str是4字节操作,需要加4个字节
	cmp r1, r2
	ble clean_bss	;改为小于等于,因为现在是复制4字节

问题

但是以以上代码直接运行的时候,我们会发现全局变量居然会被清零!!

代码重定位和位置无关码

代码重定位

之前为了全局变量在 bin 文件中使用,我们重定位了 data段。除此之外,我们也可以重定位整个代码段以达到相同的目的,接下来就是操作了。

SECTIONS {
.text 	0: {*(.text)}	
.rodata  : {*(.rodata)}	
.data	0x30000000: AT(0x800) 
{	
	data_load_addr = LOADADDR(.data);
	data_start = .;
	*(.data)
	data_end = .;
}

.bss 	 : 
{	
	. = ALIGN(4);
	bss_start = .;
	*(.bss) *(.COMMET)
	bss_end = .;
}

}

位置无关码

所谓的位置无关码,最简单的理解就是与位置无关的代码(好像没有解释一样……),一般都用代码相对地址来表示,而不用绝对地址

这里有几点需要注意的。

  • 调用程序用 B/BL 指令
  • 重定位之前不要使用绝对地址,比如:
    不可访问全局变量/静态变量
    不可以访问有初始值的数组(因为初始值放在rodata里,使用绝对地址来访问的)
  • 重定位之后,使用绝对跳转命令跳到Runtime addr, 比如:
    ldr pc, =main
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值