[Linux]代码重定位
[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 评论