ARM處理器的位置無關(guān)程序設(shè)計(jì)
ARM處理器支持位置無關(guān)的程序設(shè)計(jì),這種程序加載到存儲器的任意地址空間都可以正常運(yùn)行,其設(shè)計(jì)方法在嵌入式應(yīng)用系統(tǒng)開發(fā)中具有重要的作用。尤其在裸機(jī)狀態(tài)下開發(fā)Bootloader程序及進(jìn)行內(nèi)核初始化設(shè)計(jì);利用位置無關(guān)的程序設(shè)計(jì)方法還可以在具體應(yīng)用中用于構(gòu)建高效率動(dòng)態(tài)鏈接庫,因而了解位置無關(guān)的程序設(shè)計(jì)方法,有助于開發(fā)人員設(shè)計(jì)出結(jié)構(gòu)簡單、清晰的應(yīng)用程序。
本文引用地址:http://m.butianyuan.cn/article/150168.htm應(yīng)用程序必須經(jīng)過編譯、匯編和鏈接后才變成可執(zhí)行文件,在鏈接時(shí),要對所有目標(biāo)文件進(jìn)行重定位(relocatiON),建立符號引用規(guī)則,同時(shí)為變量、函數(shù)等分配運(yùn)行地址。當(dāng)程序執(zhí)行時(shí),系統(tǒng)必須把代碼加載到鏈接時(shí)所指定的地址空間,以保證程序在執(zhí)行過程中對變量、函數(shù)等符號的正確引用,使程序正常運(yùn)行。在具有操作系統(tǒng)的系統(tǒng)中,重定位過程由操作系統(tǒng)自動(dòng)完成。
在設(shè)計(jì)Bootloader程序時(shí),必須在裸機(jī)環(huán)境中進(jìn)行,這時(shí)Bootloader映像文件的運(yùn)行地址必須由程序員設(shè)定。通常情況下,將Bootloader程序下載到ROM的0x0地址進(jìn)行啟動(dòng),而在大多數(shù)應(yīng)用系統(tǒng)中,為了快速啟動(dòng),首先將Bootloader程序拷貝到SDRAM中再運(yùn)行。一般情況下,這兩者的地址并不相同,程序在SDRAM中的地址重定位過程必須由程序員完成。實(shí)際上,由于Bootloader是系統(tǒng)上電后要執(zhí)行的第一段程序,Bootloader程序的拷貝和在這之前的所有工作都必須由其自身來完成,而這些指令都是在ROM中執(zhí)行的。也就是說,這些代碼即使不在鏈接時(shí)所指定的運(yùn)行時(shí)地址空間,也可以正確執(zhí)行。這就是位置無關(guān)代碼,它是一段加載到任意地址空間都能正常執(zhí)行的特殊代碼。
位置無關(guān)代碼常用于以下場合:
程序在運(yùn)行期間動(dòng)態(tài)加載到內(nèi)存;
程序在不同場合與不同程序組合后加載到內(nèi)存(如共享的動(dòng)態(tài)鏈接庫);
在運(yùn)行期間不同地址相互之間的映射(如Bootloader程序)。
雖然在用GCC編譯時(shí),使用-fPIC選項(xiàng)可為C語言產(chǎn)生位置無關(guān)代碼,但這并不能修正程序設(shè)計(jì)中固有的位置相關(guān)性缺陷。特別是匯編語言代碼,必須由程序員遵循一定的程序設(shè)計(jì)準(zhǔn)則,才能保證程序的位置無關(guān)性。
ARM程序的位置無關(guān)可執(zhí)行文件PIE(PositionIndependent Executable)包括位置無關(guān)代碼PIC和位置無關(guān)數(shù)據(jù)PID(PositionIndependent Data)兩部分。
PID主要針對可讀寫數(shù)據(jù)段(.data段),其中保存已賦初值的全局變量。為實(shí)現(xiàn)其位置無關(guān)性,通常使用寄存器R9作為靜態(tài)基址寄存器,使其指向該可讀寫段的首地址,并使用相對于基址寄存器的偏移量來對該段的變量進(jìn)行尋址。這種方法常用于為可重入程序的多個(gè)實(shí)例產(chǎn)生多個(gè)獨(dú)立的數(shù)據(jù)段。在程序設(shè)計(jì)中,一般不必考慮可讀寫段的位置無關(guān)性,這主要是因?yàn)榭勺x寫數(shù)據(jù)主要分配在SDRAM中。
PIC包括程序中的代碼和只讀數(shù)據(jù)(.text段),為保證程序能在ROM和SDRAM空間都能正確運(yùn)行(如裸機(jī)狀態(tài)下的Bootloader程序),必須采用位置無關(guān)代碼程序設(shè)計(jì)。
PIC遵循只讀段位置無關(guān)ROPI(ReadOnly Position Independence)的ATPCS(ARMThumb Procedure Call STandard)的程序設(shè)計(jì)規(guī)范:
程序設(shè)計(jì)規(guī)范#e#
?。?) 程序設(shè)計(jì)規(guī)范1
引用同一ROPI段或相對位置固定的另一ROPI段中的符號時(shí),必須是基于PC的符號引用,即使用相對于當(dāng)前PC的偏移量來實(shí)現(xiàn)跳轉(zhuǎn)或進(jìn)行常量訪問。
?、?位置無關(guān)的程序跳轉(zhuǎn)。在ARM匯編程序中,使用相對跳轉(zhuǎn)指令B/BL實(shí)現(xiàn)程序跳轉(zhuǎn)。指令中所跳轉(zhuǎn)的目標(biāo)地址用基于當(dāng)前PC的偏移量來表示,與鏈接時(shí)分配給地址標(biāo)號的絕對地址值無關(guān),因而代碼可以在任何位置進(jìn)行跳轉(zhuǎn),實(shí)現(xiàn)位置無關(guān)性。
另外,還可使用ADR或ADRL偽指令將地址標(biāo)號值讀取到PC中實(shí)現(xiàn)程序跳轉(zhuǎn)。這是因?yàn)锳DR或ADRL等偽指令會被編譯器替換為對基于PC的地址值進(jìn)行操作,但這種方式所能讀取的地址范圍較小,并且會因地址值是否為字對齊而異。
但在ARM程序中,使用LDR等指令直接將地址標(biāo)號值讀取到PC中實(shí)現(xiàn)程序跳轉(zhuǎn)不是位置無關(guān)的。例如: LDR PC, =main
上面的偽指令編譯后的結(jié)果為: LDR PC, [PC, OFFSET_TO_LPOOL]
? LPOOL
DCD main
可見,雖然LDR是把基于PC的一個(gè)存儲單元LPOOL的內(nèi)容加載到PC中,但該存儲單元中保存的卻是鏈接時(shí)所決定的main函數(shù)入口的絕對地址,所以main函數(shù)實(shí)際所在的段不是位置無關(guān)。
② 位置無關(guān)的常量訪問。在應(yīng)用程序中,經(jīng)常要讀寫相關(guān)寄存器以完成必要的硬件初始化。為增強(qiáng)程序的可讀性,利用EQU偽指令對一些常量進(jìn)行賦值,但在訪問過程中,必須實(shí)現(xiàn)位置無關(guān)性。下面以PXA270的GPIO初始化介紹位置無關(guān)的常量訪問方法。
GPIO_BASE EQU 0x40e00000; GPIO基址寄存器地址
GPDR0 EQU 0x00c; 相對于GPIO基址寄存器的偏移量
init_GPDR0 EQU 0xfffbfe00; 寄存器GPDR0初值
LDR R1, =GPIO_BASE
LDR R0, =init_GPDR0
STR R0, [R1, #GPDR0]
相關(guān)推薦
技術(shù)專區(qū)
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機(jī)
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線
- 開關(guān)電源
- 單片機(jī)
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩(wěn)壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機(jī)控制
- 藍(lán)牙
- PLC
- PWM
- 汽車電子
- 轉(zhuǎn)換器
- 電源管理
- 信號放大器
評論