ARM裸板開發過程,程序的連接地址設置爲爲0x30000000,而前期的啓動代碼以及相關硬件的初始化代碼須要在內部iRAM(steppingstone,起始地址0x0)的4K中運行。
連接地址與運行地址(程序啓動後PC從0x0位置執行)不一致時,不能出現位置相關代碼。文中主要針對 SDRAM 初始化程序地址無關碼問題進行了簡單的分析。
(本文的由來是我在學習韋東山系列 ARM 裸板開發過程遇到的一個問題所引起的。在虛擬內存(MMU)操做部分,他提到了 SDRAM 初始化過程應該用位置無關的代碼實現,方式是直接對SDRAM的寄存器組賦常量值。不過在解釋爲何這樣實現就是位置無關的過程,並無解釋清楚,帶着這樣的疑問便有了如下的分析過程。)
一、位置相關的初始化過程
下面的初始化過程,因爲使用數組存儲常量值而產生了位置相關的代碼。
對於數組常量初始值的聲明unsigned long
const mem_cfg_val,不論此處是否有const關鍵字,數組元素均做爲常量存儲在常量數據區(二者反彙編代碼徹底一致)。初始化代碼的反彙編以下:
經過分析這部分代碼可知,數組中的常數變量的起始地址存儲在地址爲0x30000100內存中,即300002d0。該地址處的內容以下圖示,可見其與上述C代碼的數組常量值保持一致。上面大括號處的代碼則完成了將這些常量值從常量數據區copy到棧區的過程。這個過程之因此是位置相關的,關鍵代碼在於
ldr r3, [pc, #136] ; 30000100 <first+0x100>
二、位置無關的初始化過程
下面是位置無關的初始化代碼。該過程經過直接將初始值寫入寄存器的方式,避免了對常量值的單獨存儲,直接將其融入代碼段的二進制指令中。
反彙編以後,以下:
經過分析可知,該初始化代碼主要經過
r0, r1, r2, r3, ip 等5個寄存器來存放初始值並完成寫入SDRAM寄存器組的任務。首個初始值的賦值操做,
str r1, [r3],即p[0] = 0x22011110;爲了將 0x22011110 存入 r1,共使用了3條彙編指令。因爲ARM指令長度4字節的限制,不能直接對 r1 賦值爲 0x22011110。其餘操做與 r1 的過程相似。
整個初始化的過程並未出現對常量初始值在內存區絕對尋址的過程,故該初始化過程是位置無關的。