德国世界杯_2012年世界杯 - fyycdq.com

德国世界杯_2012年世界杯 - fyycdq.com

【裸机开发】使用汇编清除 .bss 段

目录

1、为什么要清除 .bss 段

2、使用汇编清除 .bss 段

1、为什么要清除 .bss 段

.bss 段保存的是 未被初始化 或者 初始化为0 的全局/静态变量。在编译器看来,这些东西是多余的,实际并不会给他们分配空间。因此,编译生成目标文件的时候,这些东西并不会被加载到目标文件中。目的是降低目标文件所占空间大小。

万一我们用到了这些未被初始化的全局变量(如自增),因为没有被初始化,可能会引发一些问题。这里清除 .bss 段其实就是在给 .bss 段中的变量清零,相当于给那些没有被初始化的变量赋予初值。

存储器会记下 bss 段的起始位置 __bss_start 和结束位置 __bss_end,以便于清零,等到运行程序的时候,bss 段会被加载到内存。

2、使用汇编清除 .bss 段

记录 bss 段的起始/结束位置

裸机开发时,我们可以在 lds 链接脚本中记录bss 段的起始位置和结束位置,以便于在 C 文件或者汇编文件中使用。下面的解析参考:lds 链接脚本的基本语法

SECTIONS

{

. = 0x87800000;

.text :

{

obj/start.o

*(.text)

}

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

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

. = ALIGN(4); /* 地址四字节对齐 */

__bss_start = . ; /* 记录 .bss 段的起始位置 */

.bss ALIGN(4) : { *(.bss) *(COMMON) }

__bss_end = . ; /* 记录 .bss 段的结束位置 */

}

使用汇编对 bss 段清零

.global _start

_start:

/*

其他操作

*/

ldr r0, =__bss_start @ 将lds脚本文件中的 __bss_start 加载到寄存器 r0

ldr r1, =__bss_end @ 将lds脚本文件中的 __bss_end 加载到寄存器 r0

mov r2, #0 @ r2 = 0(因为下面使用 stmia 不支持立即数操作)

bss_loop:

stmia r0!, {r2} @ 将r2寄存器的值写入到r0指向的地址,同时r0自增4字节

cmp r0, r1 @ 判断是否到达 bss 段的末尾

bne bss_loop @ 如果不等于,继续初始化

/* 其他操作 */

寄存器指令参考:

ldr赋值操作

stm 读写内存

cmp 条件执行