c语言实现代码重定位和bss段清零

目录


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

汇总点这

首先要通过 c 语言实现,就要搞清楚一个问题:怎么才能在 c 语言中获得代码的运行地址/加载地址bss段开始结束地址

两种方法

  • 通过汇编传入函数参数
  • 通过链接脚本获取

然而第一种方法是不完全的 c 语言实现,我们来实现第二种,在连接脚本里

SECTIONS
{
. = 0X30000000;

__code_start = .; //我们加入这句话,以方便 c 语言获取代码运行地址

. = ALIGN(4);
.text : {*(.text)}

. = ALIGN(4);
.rodata : {*(.rodata)}

. = ALIGN(4);
.data : {*(.data)}

. = ALIGN(4);
__bss_start = .;
.bss : {*(.bss) *(.COMMON)}
_end = .;

}

我们需要从链接脚本获取这几个“变量”

  • __code_start
  • __bss_start
  • _end

但是要怎么获取呢。在此之前,先来说说符号表(The symbol table)。在编译时,比如全局变量等都会存进符号表里,而这个符号表不会写进程序。假如有全局变量 g_A, g_B, g_C等等,而链接脚本也有“变量” __code_start,__bss_start ,_end,符号表就会这样

The symbol table
变量名:g_A
g_A的地址
变量名:g_B
g_B的地址
变量名:g_C
g_C的地址
……
“变量”名:__code_start
__code_start 的值
“变量”名:__bss_start
__bss_start 的值
“变量”名:_end
_end的值
……

如果在使用指针指向g_A 的时候,我们需要这样:

unsigned int* p = (unsigned int*)&g_A;

于是乎,为了保持代码的一致性,就算时用指针指向取链接脚本的“变量”,我们一样地写出代码:

unsigned int* p = (unsigned int* )&__code_start;

说到这里,怎么写出代码就简单了。

void copy2sdram()
{
	extern int __code_start, __bss_start, _end;	//外部变量声明,类型是什么不重要,因为都是取值

	volatile unsigned int *src  = (volatile unsigned int*)0;
	volatile unsigned int *dest = (volatile unsigned int*)&__code_start;
	volatile unsigned int *end = (volatile unsigned int*)&__bss_start;

	while (dest <= end)	//dest在这个例子为0x30000000,end为bss段的起始地址,即运行代码的结束地址
	{
		*dest++ = *src++;	//逐一赋值
	}
}

void clean_bss()
{
	extern int __bss_start, _end;	//外部变量声明,类型是什么不重要,因为都是取值


	volatile unsigned int *start = (volatile unsigned int*)&__bss_start;
	volatile unsigned int *end  = (volatile unsigned int*)&_end;

	while (start <= end)	//当bss段开始地址小于等于bss段结束地址时
	{
		*start++ = 0;	//逐一清零
	}

}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值