ARM 下的C執行程式的組成 RO RW ZI

2022-09-12 21:15:21 字數 4236 閱讀 7278

​ 一直以來對於arm體系中所描述的ro,rw和zi資料存在似是而非的理解,這段時間對其仔細了解了一番,發現了一些規律,理解了一些以前書本上有的但是不理解的東西,我想應該有不少人也有和我同樣的困惑,因此將我的一些關於ro,rw和zi的理解寫出來,希望能對大家有所幫助。要了解ro,rw和zi需要首先了解以下知識。

​ 此處所說的「arm程式」是指在arm系統中正在執行的程式,而非儲存在rom中的bin映像(image)檔案,這一點清注意區別。乙個正在執行的arm程式包含3部分:ro,rw和zi。

​ 由以上3點說明可以理解為:ro就是readonly,rw就是read/write,zi就是zero。

​ 所謂arm映像檔案就是指燒錄到rom中的bin檔案,也成為image檔案。以下用image檔案來稱呼它。

​ image檔案包含了ro和rw資料。之所以image檔案不包含zi資料,是因為zi資料都是0,沒必要包含,只要程式執行之前將zi資料所在的區域一律清零即可。包含進去反而浪費儲存空間。

​ q:為什麼image中必須包含ro和rw?

​ a:因為ro中的指令和常量以及rw中初始化過的變數是不能像zi那樣「無中生有」的。

​ 從以上兩點可以知道,燒錄到rom中的image檔案與實際執行時的arm程式之間並不是完全一樣的。因此就有必要了解arm程式是如何從rom中的image到達實際執行狀態的。

​ 實際上,ro中的指令至少應該有這樣的功能:

​ 1、將rw從rom中搬到ram中,因為rw是變數,變數不能存在rom中。

​ 在程式執行的最初階段,ro中的指令完成了這兩項工作後c程式才能正常訪問變數。否則只能執行不含變數的**。

​ 說了上面的可能還是有些迷糊,ro,rw和zi到底是什麼,下面我將給出幾個例子,最直觀的來說明ro,rw,zi在c中是什麼意思。

​ 看下面兩段程式,他們之間差了一條語句,這條語句就是宣告乙個字元常量。因此按照我們之前說的,他們之間應該只會在ro資料中相差乙個位元組(字元常量為1位元組)。

//prog1:

#include void main(void)

//prog2:

#include const char a = 5;

void main(void)

​ prog1編譯出來後的資訊如下:

code ro data rw data zi data debug

948 60 0 96 0 grand totals

total ro size(code + ro data) 1008 ( 0.98kb)

total rw size(rw data + zi data) 96 ( 0.09kb)

total rom size(code + ro data + rw data) 1008 ( 0.98kb)

​ prog2編譯出來後的資訊如下:

code ro data rw data zi data debug

948 61 0 96 0 grand totals

total ro size(code + ro data) 1009 ( 0.99kb)

total rw size(rw data + zi data) 96 ( 0.09kb)

total rom size(code + ro data + rw data) 1009 ( 0.99kb)

​ 以上兩個程式編譯出來後的資訊可以看出:

​ prog1和prog2的ro包含了code和ro data兩類資料。他們的唯一區別就是prog2的ro data比prog1多了1個位元組。這正和之前的推測一致。如果增加的是一條指令而不是乙個常量,則結果應該是code資料大小有差別。

​ 同樣再看兩個程式,他們之間只相差乙個「已初始化的變數」,按照之前所講的,已初始化的變數應該是算在rw中的,所以兩個程式之間應該是rw大小有區別。

//prog3:

#include void main(void)

//prog4:

#include char a = 5;

void main(void)

​ prog3編譯出來後的資訊如下:

code ro data rw data zi data debug

948 60 0 96 0 grand totals

total ro size(code + ro data) 1008 ( 0.98kb)

total rw size(rw data + zi data) 96 ( 0.09kb)

total rom size(code + ro data + rw data) 1008 ( 0.98kb)

​ prog4編譯出來後的資訊如下:

948 60 1 96 0 grand totals

total ro size(code + ro data) 1008 ( 0.98kb)

total rw size(rw data + zi data) 97 ( 0.09kb)

total rom size(code + ro data + rw data) 1009 ( 0.99kb)

​ 可以看出prog3和prog4之間確實只有rw data之間相差了1個位元組,這個位元組正是被初始化過的乙個字元型變數「a」所引起的。

​ 再看兩個程式,他們之間的差別是乙個未初始化的變數「a」,從之前的了解中,應該可以推測,這兩個程式之間應該只有zi大小有差別。

//prog3:

#include void main(void)

//prog4:

#include char a;

void main(void)

​ prog3編譯出來後的資訊如下:

code ro data rw data zi data debug

948 60 0 96 0 grand totals

total ro size(code + ro data) 1008 ( 0.98kb)

total rw size(rw data + zi data) 96 ( 0.09kb)

total rom size(code + ro data + rw data) 1008 ( 0.98kb)

​ prog4編譯出來後的資訊如下:

code ro data rw data zi data debug

948 60 0 97 0 grand totals

total ro size(code + ro data) 1008 ( 0.98kb)

total rw size(rw data + zi data) 97 ( 0.09kb)

total rom size(code + ro data + rw data) 1008 ( 0.98kb)

​ 編譯的結果完全符合推測,只有zi資料相差了1個位元組。這個位元組正是未初始化的乙個字元型變數「a」所引起的。

​ 注意:如果乙個變數被初始化為0,則該變數的處理方法與未初始化華變數一樣放在zi區域。

​ 即:arm c程式中,所有的未初始化變數都會被自動初始化為0。

​ 1. c中的指令以及常量被編譯後是ro型別資料。

​ 2. c中的未被初始化或初始化為0的變數編譯後是zi型別資料。

​ 3. c中的已被初始化成非0值的變數編譯後市rw型別資料。

附註:

程式的編譯命令(假定c程式名為tst.c):

armcc -c -o tst.o tst.c

armlink -noremove -elf -nodebug -info totals -info sizes -map -list aa.map -o tst.elf tst.o

編譯後的資訊就在aa.map檔案中。

rom主要指:nand flash,nor flash

ram主要指:psram,sdram,sram,ddram

可執行程式的組成

上一節分析了c語言應用程式中各段的情況,實際的c語言可執行程式,將由各個檔案經過連線生成。目標檔案是由每乙個c語言源程式 c 經過編譯器生成,目標檔案 o 的主要組成部分即 段 唯讀資料段和讀寫資料段三個段。未初始化資料段 堆和棧不會占用目標檔案的空間。可執行程式是由各個目標檔案經過連線而成。其主體...

執行程式 Linux系統下執行c 程式

引言 為什麼要在linux下寫程式?分享資料報括 c c linux,nginx,zeromq,mysql,redis,fastdfs,mongodb,zk,流 cdn,p2p,k8s,docker,tcp ip,協程,dpdk等等。首先要問一下自己,為什麼要寫這個程式。如果我們寫乙個執行在wind...

Linux下執行程式的語句

linux下編寫執行c語言程式 gcc 1.c o 1.out 1.out 假如在使用者的當前目錄下,使用vi編輯器輸入一段helloworld的 並儲存成hello.c檔案 然後執行下面的命令編譯和執行這段程式 編譯 gcc hello.c o hello 執行 hellolinux下編寫執行c ...