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