記錄一些簡單的ARM的映像檔案的內容組成及原理。
1.ARM映像檔案(axf和bin檔案)的組成。
ARM是32位處理器,地址位寬也是32位,因此其儲存空間的對應範圍可以達到4GB空間。基本上對於ARM處理器,上電或複位時都會從0x00000000出開始執行指令,因此必須保證映像檔案的起始位置放置在0x00000000處,無論是採用NAND或NOR flash,這一點都無法改變。正確放置之後,處理器會擷取到正確的指令從而順序執行。
ARM的映像檔案(即可執行檔)。產生的ARM映像檔案有分為axf和bin兩種。bin檔案時真正的可執行檔,而axf檔案是ARM特有的調試檔案,除了包含了bin檔案的內容外還包含了很多其他的調試資訊。在axf的檔案頭和檔案尾部都包含了可以用在ADW或AXF的load image的調試中。
2.ARM的映像檔案的載入域和運行域的不同
載入域映像檔案。盡量簡單地說,即那些可執行檔例如bin檔案,一般由域組成。而域由最多的三個輸出段組成即(RO、RW、ZI),RO是唯讀程式碼片段,RW是可讀寫的資料區段和ZI未初始化的資料區段。分析bin映像檔案的具體內容,也可以印證上面的內容,基本上在bin的前半部分是RO的內容而後半部分是RW的內容,ZI由於是為初始化資料,因此不需要儲存在bin檔案中。即bin檔案時RO+RW的內容的集合。而這三個輸出段又是可以由多個輸入段組成的,因為在彙編檔案中,可以設定多個段名稱,只需要在連結的時候連結到相應的位置即可,因此多個輸入段可以對應到一個輸出段上。上面所說的bin檔案都是指的是載入域的情況,因為這都是可執行檔被初始放置在flash中時各個部分的分布情況,即是載入到系統時的情況,所以叫載入域。但系統此時是並不能啟動並執行。
載入域的映像檔案必須順利地過渡到運行時域,這時系統才能夠正確地被執行。因為有個很明顯的一點,程式一般都固化在flash中。而flash是唯讀,上面也說到可讀寫的RW資料區段的內容是跟在RO段後面(即bin檔案中),被放置在了flash上,RW段要求可讀寫,flash顯然不滿足要求,因此載入域必須過渡到運行時域。最直觀的理解就是,我們必須把RW段的內容轉移到可讀寫的SDRAM或SRAM上去,因此就引發了運行域的問題。
如何轉換,如何保證前面RO段的程式的內容能夠正確地定址到被轉移了的RW段的內容。因為大部分組譯工具的轉移指令都是絕對定址的,比較少的偽指令能提供相對定址,絕對定址的效率顯然比較高。因此我們必須在代碼中就必須知道將來運行時RW段被放置在了什麼一個地方。在程式連結之後,所有的代碼中的地址都將固定。解決這樣的問題也並不複雜,需要連結器確保RO段的運行時起始地址和RW段的運行時起始地址,這就是為什麼我們要在ADS設定串連選項ro_base和rw_base的目的了。所有的RO段的地址都是基於ro_base指定的內容,而所有程式碼片段的內容也是基於rw_base上的,這樣程式在連結後就已經確定了所有的相對位址,剩下的事就是將相應的段的內容從載入域的位置搬移到運行時域的位置。
這樣的代碼搬移的工作如果是在調試狀態的話,一般調試器就會幫我們做好所有事情了,而如果是在非調試狀態,就需要我們自己複製程式碼片段的搬移工作,有趣的是,不少ARM都支援從NAND flash中啟動,而NAND flash本身就是不能直接執行的,需要將代碼搬移到SDRAM中,因此這裡的運行時域和載入域的區別被屏蔽掉了。一般我們做代碼搬移這樣的工作的時候,採用的跳轉地址都要用相對跳轉指令。這樣的好處是,無論使用者將程式載入到什麼地址,代碼搬移指令都能正確地將程式從載入域轉換到運行時域,從而保證程式順利執行。