KEIL的ARM编译器对RW和ZI段的一个处理

按照C编译器编译的结果,一般会产生RO段,RW段,ZI段。RO是程序中的指令和常量,RW是程序中的已初始化全局变量,ZI是程序中的未初始化或初始化为零的全局变量。

那么如下的代码

1 int aaa;

2 int bbb;

3 

4 int main()

5 {

6     aaa = 7;

7     bbb = 8;

8     return 0;

9 }

应该产生的是八个字节的ZI段,但很奇怪,--bss_threshold=0 

Program Size: Code=464 RO-data=268 RW-data=8 ZI-data=608  

如上所示,其中的Code段,RO-data段和ZI-data段是启动代码产生的,这里不深究。

它产生了8个字节的RW段,可以分析产生的map文件查看main汇编代码和RW段,发现的确将aaa和bbb分配在了RW段。

map文件中的符号如下:

aaa      0x20000000   Data           4  main.o(.data)

bbb      0x20000004   Data           4  main.o(.data)



Execution Region RW_IRAM1 (Base: 0x20000000, Size: 0x00000268, Max: 0x00001000, ABSOLUTE)



Base Addr Size Type Attr Idx E Section Name Object



0x20000000 0x00000008 Data RW 11 .data main.o

想想没道理,尝试发现初始化了的全局变量也是放在RW段。

最后发现罪魁祸首是KEIL的armcc的“--bss_threshold=num”这个编译选项,查看手册介绍如下:

This option controls the placement of small global ZI data items in sections. A small global ZI data item is an uninitialized data item that is eight bytes or less in size. 
--bss_threshold=num

where:

num

is either:

0

place small global ZI data items in ZI data sections

8

place small global ZI data items in RW data sections.

In ARM Compiler 4.1 and later, the compiler might place small global ZI data items in RW data sections as an optimization. In RVCT 2.0.1 and earlier, small global ZI data items were placed in ZI data sections by default.

Use --bss_threshold=0 to emulate the behavior of RVCT 2.0.1 and earlier with respect to the placement of small global ZI data items in ZI data sections.

将比较小的全局ZI变量存放到RW段当中作为优化手段,默认是小于8个字节的当做small global ZI data,也就是说char,int这些类型全部会放到ZI,除非是大于8个字节的数组。

知道这个之后在编译选项里面添加--bss_threshold=0就可以将其恢复到正常的ZI段中了。

gcc的arm编译器编出来的就是正常的放在ZI段的,感觉keil这样做没什么道理,万一少字节的全局变量很多的话就增加了很大的bin size。

当然全局变量太多也不是一个有素质的程序员应该写出的代码。

 

 

你可能感兴趣的:(ARM)