裸机代码(uboot) : clear bss
一. bss介绍:
代码中函数、变量、常量 / bss段、data段、text段 /sct文件、.map文件的关系[实例分析arm代码(mdk)]
bss和data的区别: 全局的未初始化变量存在于.bss段中,具体体现为一个占位符; 全局的已初始化变量存于.data段中; .bss是不占用.exe文件空间的,其内容由操作系统初始化(清零); 而.data却需要占用,其内容由程序初始化。 若这样定义一个全局变量:int g_inBss[9] ; 则它在.bss段,这里占用占位符的空间。 若这样定义一个全局变量:int g_inData[9] ={1,2,3,4,5,6,7,8,9}; 则它在.data段,程序占用数组全部大小的空间。 bss和data的联系: 都在rw区域; bss段在运行起来成为进程之后,占的空间大小和data就相同了。
二. 分析uboot代码中的clearbss段的代码:
_bss_start 和 __bss_start
====================================
1. u-boot-1.1.6/board/100ask24x0/u-boot.lds
......
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
board/100ask24x0/boot_init.o (.text)
*(.text)
}
......
......
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
__bss_start 是bss段的起始地址,
_end 是bss段的终止地址.
====================================
2. u-boot-1.1.6/cpu/arm920t/start.S
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
分析{
.word .word expr {,expr}… 分配一段字内存单元,幵用expr初始化字内存单元(32bit)
关亍 _bss_start 和 _bss_end 都是两个标号,对应着此处的地址。
而两个地址里面分别存放的值是 __bss_start 和 _end,
}
====================================
3. 汇编的清零bss段:
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l: str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
{
ldr r0, _bss_start 表示装载 _bss_start 地址中的值,即装载 __bss_start
ldr r0, _bss_end 表示装载 _bss_end 地址中的值,即装载 _end
}
====================================
4. 网上找的c语言中的clear_bss, 觉得有问题:
void clean_bss(void)
{
extern int __bss_start, _end;
int *p = &__bss_start;
for (; p < &_end; p++)
*p = 0;
}
&__bss_start 就是: _bss_start
&_end 就是: _bss_end
从c语言语法上看,__bss_start和_end和bss段代表bss段的起始地址和终止地址.
但是_bss_start和_bss_end却不能代表bss段的起始地址和终止地址, 因此我得出了这个结论: "clean_bss中那个for循环并不能起到清零bss段的作用."