- 相关推荐
C言语KEIL的ARM编译器对RW和ZI段的处理
按照C编译器编译的结果,一般会产生RO段,RW段,ZI段。RO是程序中的指令和常量,RW是程序中的已初始化全局变量,ZI是程序中的未初始化或初始化为零的全局变量。下面是小编为大家带来的C言语KEIL的ARM编译器对RW和ZI段的处理的知识,欢迎阅读。
按照C编译器编译的结果,一般会产生RO段,RW段,ZI段。RO是程序中的指令和常量,RW是程序中的已初始化全局变量,ZI是程序中的未初始化或初始化为零的全局变量。
那么如下的代码
int aaa;
int bbb;
int main()
{
aaa = 7;
bbb = 8;
return 0;
}
应该产生的是八个字节的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 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:
place small global ZI data items in ZI data sections
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。
当然全局变量太多也不是一个有素质的程序员应该写出的代码。
一、含义解释:
Code:即代码域,它通常是指编译器生成的机器指令,这些内容会被存储到ROM区。
RO-data:Read Only data,即只读数据域,它指程序中用到的只读数据,这些数据被存储在ROM区,因而程序不能被修改的内容。例如C语言中const关键字定义的变量就是典型的RO-data。
RW-data:Read Write data,即可读写数据域,它指初始化为“非0值”的可读写数据,程序刚运行时,这些数据具有非0的初始值,程序运行的时候它们又会常驻在RAM区,应用程序可以修改其内容。例如C语言中定义的全局变量,且定义时赋予“非0值”给该变量。
ZI-data:Zero Initialie data,即0初始化数据,它指初始化为“0值”的可读写数据域,它与RW-data的区别是程序刚运行时这些数据初始值全都为0,程序运行时和RW-data的性质一样,它们也常驻在RAM区,应用程序可以更改其内容。例如C语言中使用定义的全局变量,且定义时赋予“0值”给该变量(如若定义该变量时没有赋予初始值,编译器会把它当ZI-data来对待,初始化为0);
二、程序存储详解:
关于哪些数据存储在Flash区域,哪些数据存储在SRAM区域,这就涉及到程序的存储状态了,应用程序具有静止和运行两种状态。静止态的程序被存储在非易失存储器中,如内部FLASH区域,因而系统掉电后也能正常保存。但是当程序在运行状态的时候,程序常常需要修改一些暂存数据(例如初始化非0值的数据),这些数据往往存放在Flash中,但是由于需要被修改,所以这些数据在程序运行的时候需要被复制到RAM中。因此,程序在静止与运行的时候它在存储器中的表现是不一样的。
三、程序占用Flash和SRAM的空间计算:
GD32的RO区域不需要加载到SRAM,内核直接从FLASH读取指令运行。当程序存储到芯片的内部FLASH时(即ROM区),它占用的空间是Code、RO-data及RW-data的总和,所以如果这些内容比芯片的FLASH空间大,程序就无法被正常保存在芯片的FLASH了。当程序在执行的时候,需要占用内部SRAM空间(即RAM区),占用的空间包括RW-data和ZI-data空间之和。
总结:程序需要下载到芯片的FLASH空间,FLASH的最小空间应该大于Code +ROData +RWData的总和;
程序运行的时候,芯片内部RAM使用的空间应该大于RWData+ZIData之和;
【C言语KEIL的ARM编译器对RW和ZI段的处理】上海花千坊相关的文章:
C语言编译器和IDE的选择之间的关系10-18
C语言预处理概述03-30
有趣的C语言预处理12-04
C语言预处理知识11-26
c#中预处理指令#if的使用11-30
浅谈c语言和c++和VB的区别04-02
幼儿园中班《ga zi ga zi 拉大锯》教学设计04-01
C语言之字符串处理函数04-01
C语言函数的递归和调用11-28
C语言项目中.h文件和.c文件的关系详解05-08