- 相關(guān)推薦
C言語KEIL的ARM編譯器對RW和ZI段的處理
按照C編譯器編譯的結(jié)果,一般會產(chǎn)生RO段,RW段,ZI段。RO是程序中的指令和常量,RW是程序中的已初始化全局變量,ZI是程序中的未初始化或初始化為零的全局變量。下面是小編為大家?guī)淼腃言語KEIL的ARM編譯器對RW和ZI段的處理的知識,歡迎閱讀。
按照C編譯器編譯的結(jié)果,一般會產(chǎn)生RO段,RW段,ZI段。RO是程序中的指令和常量,RW是程序中的已初始化全局變量,ZI是程序中的未初始化或初始化為零的全局變量。
那么如下的代碼
int aaa;
int bbb;
int main()
{
aaa = 7;
bbb = 8;
return 0;
}
應(yīng)該產(chǎn)生的是八個字節(jié)的ZI段,但很奇怪,--bss_threshold=0
Program Size: Code=464 RO-data=268 RW-data=8 ZI-data=608
如上所示,其中的Code段,RO-data段和ZI-data段是啟動代碼產(chǎn)生的,這里不深究。
它產(chǎn)生了8個字節(jié)的RW段,可以分析產(chǎn)生的map文件查看main匯編代碼和RW段,發(fā)現(xiàn)的確將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
想想沒道理,嘗試發(fā)現(xiàn)初始化了的全局變量也是放在RW段。
最后發(fā)現(xiàn)罪魁禍?zhǔn)资荎EIL的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段當(dāng)中作為優(yōu)化手段,默認是小于8個字節(jié)的當(dāng)做small global ZI data,也就是說char,int這些類型全部會放到ZI,除非是大于8個字節(jié)的數(shù)組。
知道這個之后在編譯選項里面添加--bss_threshold=0就可以將其恢復(fù)到正常的ZI段中了。
gcc的arm編譯器編出來的就是正常的放在ZI段的,感覺keil這樣做沒什么道理,萬一少字節(jié)的全局變量很多的話就增加了很大的bin size。
當(dāng)然全局變量太多也不是一個有素質(zhì)的程序員應(yīng)該寫出的代碼。
一、含義解釋:
Code:即代碼域,它通常是指編譯器生成的機器指令,這些內(nèi)容會被存儲到ROM區(qū)。
RO-data:Read Only data,即只讀數(shù)據(jù)域,它指程序中用到的只讀數(shù)據(jù),這些數(shù)據(jù)被存儲在ROM區(qū),因而程序不能被修改的內(nèi)容。例如C語言中const關(guān)鍵字定義的變量就是典型的RO-data。
RW-data:Read Write data,即可讀寫數(shù)據(jù)域,它指初始化為“非0值”的可讀寫數(shù)據(jù),程序剛運行時,這些數(shù)據(jù)具有非0的初始值,程序運行的時候它們又會常駐在RAM區(qū),應(yīng)用程序可以修改其內(nèi)容。例如C語言中定義的全局變量,且定義時賦予“非0值”給該變量。
ZI-data:Zero Initialie data,即0初始化數(shù)據(jù),它指初始化為“0值”的可讀寫數(shù)據(jù)域,它與RW-data的區(qū)別是程序剛運行時這些數(shù)據(jù)初始值全都為0,程序運行時和RW-data的性質(zhì)一樣,它們也常駐在RAM區(qū),應(yīng)用程序可以更改其內(nèi)容。例如C語言中使用定義的全局變量,且定義時賦予“0值”給該變量(如若定義該變量時沒有賦予初始值,編譯器會把它當(dāng)ZI-data來對待,初始化為0);
二、程序存儲詳解:
關(guān)于哪些數(shù)據(jù)存儲在Flash區(qū)域,哪些數(shù)據(jù)存儲在SRAM區(qū)域,這就涉及到程序的存儲狀態(tài)了,應(yīng)用程序具有靜止和運行兩種狀態(tài)。靜止態(tài)的程序被存儲在非易失存儲器中,如內(nèi)部FLASH區(qū)域,因而系統(tǒng)掉電后也能正常保存。但是當(dāng)程序在運行狀態(tài)的時候,程序常常需要修改一些暫存數(shù)據(jù)(例如初始化非0值的數(shù)據(jù)),這些數(shù)據(jù)往往存放在Flash中,但是由于需要被修改,所以這些數(shù)據(jù)在程序運行的時候需要被復(fù)制到RAM中。因此,程序在靜止與運行的時候它在存儲器中的表現(xiàn)是不一樣的。
三、程序占用Flash和SRAM的空間計算:
GD32的RO區(qū)域不需要加載到SRAM,內(nèi)核直接從FLASH讀取指令運行。當(dāng)程序存儲到芯片的內(nèi)部FLASH時(即ROM區(qū)),它占用的空間是Code、RO-data及RW-data的總和,所以如果這些內(nèi)容比芯片的FLASH空間大,程序就無法被正常保存在芯片的FLASH了。當(dāng)程序在執(zhí)行的時候,需要占用內(nèi)部SRAM空間(即RAM區(qū)),占用的空間包括RW-data和ZI-data空間之和。
總結(jié):程序需要下載到芯片的FLASH空間,F(xiàn)LASH的最小空間應(yīng)該大于Code +ROData +RWData的總和;
程序運行的時候,芯片內(nèi)部RAM使用的空間應(yīng)該大于RWData+ZIData之和;
【C言語KEIL的ARM編譯器對RW和ZI段的處理】相關(guān)文章:
C語言編譯器和IDE選擇05-27
C語言編譯器和IDE的選擇06-30
C/C++編譯器錯誤消息大全03-11
C語言編譯器gcc命令如何操作06-04
C語言編譯器gcc命令如何操作步驟02-21
C語言程序的段06-14
C語言的預(yù)處理08-02