般而言,乙個程式包括唯讀的**段和可讀寫的資料段。
在arm的整合開發環境中,唯讀的**段和常量被稱作ro段(readonly);可讀寫的全域性變數和靜態變數被稱作rw段(readwrite);rw段中要被初始化為零的變數被稱為zi段(zeroinit)。
對於嵌入式系統而言,程式映象都是儲存在flash儲存器等一些非易失性器件中的,而在執行時,程式中的rw段必須重新裝載到可讀寫的ram中。這就涉及到程式的載入時域和執行時域。簡單來說,程式的
載入時域
就是指程式燒入flash中的狀態,
執行時域
是指程式執行時的狀態。對於比較簡單的情況,可以在ads整合開發環境的arm linker選項中指定ro base和rw base,告知聯結器ro和rw的連線基位址。對於複雜情況,如ro段被分成幾部分並對映到儲存空間的多個地方時,需要建立乙個稱為「分布裝載描述檔案」的文字檔案,通知聯結器把程式的某一部分連線在儲存器的某個位址空間。需要指出的是,分布裝載描述檔案中的定義要按照系統重定向後的儲存器分布情況進行。在引導程式完成初始化的任務後,應該把主程式轉移到ram中去執行,以加快系統的執行速度。
什麼是arm的映像檔案,
arm映像檔案其實就是可執行檔案,包括bin或hex兩種格式,可以直接燒到rom裡執行。
在axd除錯過程中,我們除錯的是axf檔案,其實這也是一種映像檔案,它只是在bin檔案中加了乙個檔案頭和一些除錯資訊。
映像檔案一般由域組成,域最多由三個輸出段組成(ro,rw,zi)組成,輸出段又由輸入段組成。所謂域,指的就是整個bin映像檔案所處在的區域,它又分為載入域和執行域。
載入域就是映像檔案被靜態存放的工作區域,一般來說flash裡的 整個bin檔案所在的位址空間就是載入域,當然在程式一般都不會放在 flash裡執行,一般都會搬到sdram裡執行工作,它們在被搬到sdram裡工作所處的位址空間就是執行域。我們輸入的**,一般有**部分和資料部分,這就是所謂的輸入段,經過編譯後就變成了bin檔案中ro段和rw段,還有所謂的zi段,這就是輸出段。
對於載入域中的輸出段,一般來說ro段後面緊跟著rw段,rw段後面緊跟著zi段。
在執行域中這些輸出段並不連續,但rw和zi一定是連著的。zi段和rw段中的資料其實可以是rw屬性。
| image$$ro$$base| |image$$ro$$limit| |image$$rw$$base| |image$$zi$$base| |image$$zi$$limit|這幾個變數是編譯器通知的,我們在 makefile檔案中可以看到它們的值。它們指示了在執行域中各個輸出段所處的位址空間,
| image$$ro$$base| 就是ro段在執行域中的起始位址,|image$$ro$$limit| 是ro段在執行域中的截止位址,其它依次類推。
我們可以在linker的output中指定,在 ******模式中,ro base對應的就是| image$$ro$$base|,rw base 對應的是|image$$rw$$base|,
由於rw和zi相連,|image$$zi$$base| 就等於|image$$rw$$limit|
。其它的值都是編譯器自動計算出來的。
下面是2410啟動**的搬運部分,我給出注釋:
baseofrom dcd |image$$ro$$base|
topofrom dcd |image$$ro$$limit|
baseofbss dcd |image$$rw$$base|
baseofzero dcd |image$$zi$$base|
endofbss dcd |image$$zi$$limit|
adr r0, resetentry; resetentry是復位執行時域的起始位址,在boot nand中一般是0
ldr r2, baseofrom;
cmp r0, r2
ldreq r0, topofrom;topofrom=0x30001de0,**段位址的結束
beq initram
ldr r3, topofrom
;part 1,通過比較,將ro搬到sdram裡,搬到的目的位址從 | image$$ro$$base| 開始,到|image$$ro$$limit|結束
0 ldmia r0!, ;將r0值作為位址處(resetentry)連續的4個32位數依次轉入r4,r5,r6,r7;同時r0增加。
stmia r2!, ;將r4,r5,r6,r7的值依次存入|image$$ro$$base|位址處;同時r2增加。
cmp r2, r3
bcc %b0;
;part 2,搬rw段到sdram,目的位址從|image$$rw$$base| 開始,到|image$$zi$$base|結束
sub r2, r2, r3;r2=0 ;上面拷貝時每次拷貝4個雙字(32位)大小,但是ro段大小不一定是4的整數倍,所以可能多拷貝了幾個雙字大小,r2-r3得到多拷貝的個數
sub r0, r0, r2 ;
r0-(r2-r3)可以使r0指向在boot nand中ro的結束位址
initram ;carry rw to baseofbss
ldr r2, baseofbss ;topofrom=0x30001de0,baseofrw
ldr r3, baseofzero ;baseofzero=0x30001de0
0cmp r2, r3
ldrcc r1, [r0], #4
strcc r1, [r2], #4
bcc %b0
;part 3,將sdram zi初始化為0,位址從|image$$zi$$base|到|image$$zi$$limit|
mov r0, #0;init 0
ldr r3, endofbss;endofbss=30001e40
1 cmp r2, r3
strcc r0, [r2], #4
bcc %b1
至此三個輸出段組成(ro,rw,zi)拷貝和初始化結束。
作用域的理解
什麼是作用域 作用域就是一套規則,控制著變數和函式的可訪問範圍。作用域外無法引用作用域內的變數,離開作用域後,作用域的變數的記憶體空間會被清楚,比如執行完函式。什麼是預解析 就是在瀏覽器解析 之前,把變數的宣告和函式的宣告提公升到該作用域的最上面 什麼是變數提公升 變數提公升就是在進入乙個執行上下文...
靜態域,公有域和例項域的區別
此部分內容需對jvm有一定了解,如有疑惑請移步jvm原理 變數 靜態變數會copy乙份到堆內,方法區外的靜態物件中,那麼它屬於靜態域,可被所有執行緒共享,一旦成為共享變數後,最好使用原子操作類替代。塊 靜態 塊會copy乙份到堆內,方法區外的靜態物件中,那麼它屬於靜態域,只會在第一次初始化物件時執行...
全域性作用域 函式作用域 塊級作用域的理解
作用域是任何一門程式語言中的重中之重,因為它控制著變數與引數的可見性與生命週期。很慚愧,我今天才深入理解js的作用域.我不配做乙個程式設計師.開玩笑,什麼時候理解都不晚,重要的是理解了以後能不能深深地扎在記憶裡,不能,那就寫下來在乙個 塊 括在一對花括號中的一組語句 中定義的所有變數在 塊的外部是不...