裸机代码(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段的作用."

 

原文地址:https://www.cnblogs.com/mylinux/p/5604458.html