[Linux]代码重定位

001.png

[Linux]代码重定位

linux学习记录,用总结不太好hhhh

艾恩凝 2021/3/30

introduction

这东西也是刚刚接触,云里雾里的,懂了个大概,像我用的这个板子,有nor flash,nandflash,sram,SDRAM,启动方式有两种。一种是nor,一种是nand,sram只有4k内存,假如一个程序超过了4k,这又怎么办呢,这就需要这个了,我觉得一般就是解决储存不够的问题,这样说又不恰当,像nand启动,把代码复制到sram上进行启动,如果超过4k那就复制前4k。首先用汇编进行实现,之后汇编C交替使用,能用c就不用汇编。

另外这东西分为这么几种,代码段,数据段,全局变量那个段,还有bss段,就是初值为0,或只有声明的参数。重定位引入后缀为lds链接文件。

ps,越来越喜欢这个,不了解不知道,真的佩服设计这些东西的人,到最后声明都变成了01,不变成了电流和没有电流。

重定位_汇编实现

有点不太会表述,半吊子,懂了会直接贴代码hhhh

下面是链接文件,怎么看我不知道无法描述,就是会看

 1SECTIONS
 2{
 3	. = 0x30000000;
 4
 5	. = ALIGN(4);
 6	.text      :
 7	{
 8	  *(.text)
 9	}
10
11	. = ALIGN(4);
12	.rodata : { *(.rodata) }
13
14	. = ALIGN(4);
15	.data : { *(.data) }
16
17	. = ALIGN(4);
18	__bss_start = .;
19	.bss : { *(.bss) *(.COMMON) }
20	_end = .;
21}
22

start.S中汇编

 1	bl sdram_init /*初始化SDRAM*/
 2
 3	/* 重定位text, rodata, data段整个程序 */
 4	mov r1, #0
 5	ldr r2, =_start 	    /* 第1条指令运行时的地址 */
 6	ldr r3, =__bss_start    /* bss段的起始地址 */  /*_start 起始地址,此处__bss_start 是链接文件里的*/
 7
 8cpy:
 9	ldr r4, [r1]
10	str r4, [r2]       /* 这两行代码不用说了吧,读取r1地址的值,并写到,r2地址上*/
11	add r1, r1, #4
12	add r2, r2, #4
13	cmp r2, r3
14	ble cpy            /*比较 循环 说白了就是搬运*/
15
16
17	/* 清除BSS段 */
18	ldr r1, =__bss_start
19	ldr r2, =_end
20	mov r3, #0
21clean:
22	str r3, [r1]
23	add r1, r1, #4
24	cmp r1, r2
25	ble clean
26
27	//bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */
28	ldr pc, =main  /* 绝对跳转, 跳到SDRAM */
29

重定位_C汇编交替实现

链接文件就是加了个地址定位

 1SECTIONS
 2{
 3	. = 0x30000000;
 4
 5	__code_start = .;
 6
 7	. = ALIGN(4);
 8	.text      :
 9	{
10	  *(.text)
11	}
12
13	. = ALIGN(4);
14	.rodata : { *(.rodata) }
15
16	. = ALIGN(4);
17	.data : { *(.data) }
18
19	. = ALIGN(4);
20	__bss_start = .;
21	.bss : { *(.bss) *(.COMMON) }
22	_end = .;
23}
24

start.S中汇编

 1
 2	bl sdram_init
 3	//bl sdram_init2	 /* 用到有初始值的数组, 不是位置无关码 */
 4
 5	/* 重定位text, rodata, data段整个程序 */
 6	bl copy2sdram
 7
 8	/* 清除BSS段 */
 9	bl clean_bss
10
11	//bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */
12	ldr pc, =main  /* 绝对跳转, 跳到SDRAM */

接下来就是用C语言实现了,C语言就好说了

 1void copy2sdram(void)
 2{
 3	/* 要从lds文件中获得 __code_start, __bss_start
 4	 * 然后从0地址把数据复制到__code_start
 5	 */
 6	extern int __code_start, __bss_start;
 7
 8	volatile unsigned int *dest = (volatile unsigned int *)&__code_start;
 9	volatile unsigned int *end = (volatile unsigned int *)&__bss_start;
10	volatile unsigned int *src = (volatile unsigned int *)0;
11
12	while (dest < end)
13	{
14		*dest++ = *src++;
15	}
16}
17void clean_bss(void)
18{
19	/* 要从lds文件中获得 __bss_start, _end
20	 */
21	extern int _end, __bss_start;
22	volatile unsigned int *start = (volatile unsigned int *)&__bss_start;
23	volatile unsigned int *end = (volatile unsigned int *)&_end;
24	while (start <= end)
25	{
26		*start++ = 0;
27	}
28}
29

C语言代码就看起来简单了

conclusion

重定位需要消化消化,重在理解,每次总想写个好的记录,最终都是怎么简单怎么来,好烦

    评论
    0 评论
avatar

取消