清除BSS段(ZI段)
1、C语言中的BSS段
(1)程序里的全局变量,如果它的初始值为0,或者没有设置初始值,这些变量被放在BSS段里,也叫ZI段。
char g_Char = 'A';
const char g_Char2 = 'B';
int g_A = 0; // 放在BSS段
int g_B; // 放在BSS段(2)BSS段并不会放入bin文件中,否则也太浪费空间了。 在使用BSS段里的变量之前,把BSS段所占据的内存清零就可以了。
(3)注意:对于keil来说,一个本该放到BSS段的变量,如果它所占据的空间小于等于8字节自己,keil仍然会把它放在data段里。只有当它所占据的空间大于8字节时,才会放到BSS段。
int g_A[3] = {0, 0}; // 放在BSS段
char g_B[9]; // 放在BSS段int g_A[2] = {0, 0}; // 放在data段
char g_B[8]; // 放在data段2、清除BSS段
2.1、BSS段在哪?多大?
(1)在散列文件中,BSS段(ZI段)在可执行域RW_IRAM1中描述,.ANY (+RW +ZI):
- RW::可读可写的数据段
- ZI:BSS段
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08000000 0x00100000 { ; load region size_regionER_IROM1 0x08000000 0x00100000 { ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}RW_IRAM1 0x20000000 0x00030000 { ; RW data.ANY (+RW +ZI)}
}(2)BSS段(ZI段)的链接地址(基地址)、长度,使用下面的符号获得:

2.2、怎么清除BSS段
2.2.1、汇编码
IMPORT |Image$$RW_IRAM1$$ZI$$Base|
IMPORT |Image$$RW_IRAM1$$ZI$$Length|
IMPORT memsetLDR R0, = |Image$$RW_IRAM1$$ZI$$Base| ; DEST
LDR R1, = |Image$$RW_IRAM1$$ZI$$Length| ; Length
BL memset2.2.2、C语言
(1)方法1 声明为外部变量,使用时需要使用取址符:
extern int Image$$RW_IRAM1$$ZI$$Base;
extern int Image$$RW_IRAM1$$ZI$$Length;memset(&Image$$RW_IRAM1$$ZI$$Base, 0, &Image$$RW_IRAM1$$ZI$$Length);(2)声明为外部数组,使用时不需要使用取址符:
extern char Image$$RW_IRAM1$$ZI$$Base[];
extern int Image$$RW_IRAM1$$ZI$$Length[];memset(Image$$RW_IRAM1$$ZI$$Base[], 0, Image$$RW_IRAM1$$ZI$$Length);3、map文件
(1)在Listings文件下能找到map文件

(2)通过map文件查看变量所属的段
- g_val_a在.data段
g_val_a 0x20000004 Data 4 main.o(.data)- g_val_b在.bss段
g_val_b 0x2000000c Data 40 main.o(.bss)