從0學(xué)ARM——什么是位置無(wú)關(guān)碼?
二、怎么實(shí)現(xiàn)位置無(wú)關(guān)碼?
1. 什么是《編譯地址》?什么是《運(yùn)行地址》?
「編譯地址:」
32位的處理器,它的每一條指令是4個(gè)字節(jié),以4個(gè)字節(jié)存儲(chǔ)順序,進(jìn)行順序執(zhí)行,CPU是順序執(zhí)行的,只要沒(méi)發(fā)生什么跳轉(zhuǎn),它會(huì)順序進(jìn)行執(zhí)行, 編譯器會(huì)對(duì)每一條指令分配一個(gè)編譯地址,這是編譯器分配的,在編譯過(guò)程中分配的地址,我們稱之為編譯地址。
「運(yùn)行地址:」
是指程序指令真正運(yùn)行的地址,是由用戶指定的,用戶將運(yùn)行地址燒錄到哪里,哪里就是運(yùn)行的地址。比如有一個(gè)指令的編譯地址是0x40008000,實(shí)際運(yùn)行的地址是0x40008000,如果用戶將指令燒到0x60000000上,那么這條指令的運(yùn)行地址就是0x60000000。
當(dāng)編譯地址和運(yùn)行地址不同的時(shí)候會(huì)出現(xiàn)什么結(jié)果?結(jié)果是不能跳轉(zhuǎn),編譯后會(huì)產(chǎn)生跳轉(zhuǎn)地址,如果實(shí)際地址和編譯后產(chǎn)生的地址不相等,那么就不能跳轉(zhuǎn)。
「C語(yǔ)言編譯地址:」
都希望把編譯地址和實(shí)際運(yùn)行地址放在一起的,但是匯編代碼因?yàn)椴恍枰鯟語(yǔ)言到匯編的轉(zhuǎn)換,可以直接的去寫地址,所以直接寫的就是他的運(yùn)行地址,這就是為什么任何bootloader剛開始會(huì)有一段匯編代碼,因?yàn)槠鹗即a編譯地址和實(shí)際地址不相等,這段代碼和匯編無(wú)關(guān),跳轉(zhuǎn)用的運(yùn)行地址。
2. 舉例
實(shí)現(xiàn)位置無(wú)關(guān)碼主要考慮以下兩個(gè)方面:
1. 位置無(wú)關(guān)的函數(shù)跳轉(zhuǎn)
2. 位置無(wú)關(guān)的常量訪問(wèn)
下面我們通過(guò)兩個(gè)例子詳細(xì)講解。
代碼
編譯代碼使用的連接文件「map.lds」如下:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x40008000;
. = ALIGN(4);
.text :
{
gcd.o(.text)
*(.text)
}
. = ALIGN(4);
.rodata :
{ *(.rodata) }
. = ALIGN(4);
.data :
{ *(.data) }
. = ALIGN(4);
.bss :
{ *(.bss) }
}
如文件map.lds所示:「0x40008000」就是鏈接地址,
其他源文件如下:「gcd.s」
.text
.global _start
_start:
ldr sp,=0x70000000 get stack top pointer
bl func
ldr pc,=func
b main
func:
mv pc,lr
「main.c」
* main.c
*
* Created on: 2020-12-12
* Author: 一口Linux
int aaaa=0;
int main(void)
{
aaaa = 0x11;
while(1);
return 0;
}
「Makefile」
TARGET=gcd
TARGETC=main
all:
arm-none-linux-gnueabi-gcc -O1 -g -c -o $(TARGETC).o $(TARGETC).c
arm-none-linux-gnueabi-gcc -O1 -g -c -o $(TARGET).o $(TARGET).s
arm-none-linux-gnueabi-gcc -O1 -g -S -o $(TARGETC).s $(TARGETC).c
arm-none-linux-gnueabi-ld $(TARGETC).o $(TARGET).o -Tmap.lds -o $(TARGET).elf
arm-none-linux-gnueabi-objcopy -O binary -S $(TARGET).elf $(TARGET).bin
arm-none-linux-gnueabi-objdump -D $(TARGET).elf > $(TARGET).dis
clean:
rm -rf *.o *.elf *.dis *.bin
反匯編文件「gcd.dis」
如上圖所示:
_start對(duì)應(yīng)的鏈接地址是0x400080009行 bl func對(duì)應(yīng)的指令10行 ldr pc,=pc對(duì)應(yīng)的指令func的鏈接地址0x40008010全局變量aaaa對(duì)應(yīng)的內(nèi)存位于bss段0x4000802c19行 aaaa = 0x11 賦值語(yǔ)句對(duì)應(yīng)的機(jī)器碼

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
3月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
4月30日立即下載>> 【村田汽車】汽車E/E架構(gòu)革新中,新智能座艙挑戰(zhàn)的解決方案
-
5月15-17日立即預(yù)約>> 【線下巡回】2025年STM32峰會(huì)
-
即日-5.15立即報(bào)名>>> 【在線會(huì)議】安森美Hyperlux™ ID系列引領(lǐng)iToF技術(shù)革新
-
5月15日立即下載>> 【白皮書】精確和高效地表征3000V/20A功率器件應(yīng)用指南
-
5月16日立即參評(píng) >> 【評(píng)選啟動(dòng)】維科杯·OFweek 2025(第十屆)人工智能行業(yè)年度評(píng)選
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達(dá)AI統(tǒng)治的開始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 “AI寒武紀(jì)”爆發(fā)至今,五類新物種登上歷史舞臺(tái)
- 4 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 5 國(guó)產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計(jì)算迎來(lái)商業(yè)化突破,但落地仍需時(shí)間
- 7 東陽(yáng)光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開成長(zhǎng)空間
- 8 地平線自動(dòng)駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營(yíng)收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機(jī)器人東風(fēng)翻身?