编译过程中的链接地址对最终编译镜像文件的影响
MDK和交叉編譯工具編譯時(shí)都會(huì)指定程序的下載的地址(其實(shí)就是告訴程序它將在那個(gè)地址上開始執(zhí)行),這有什么意義嗎?
其實(shí)這么設(shè)計(jì)有原因的,因?yàn)檫@里涉及到全局變量和全局函數(shù)指針的地址問題,加入當(dāng)你在編譯時(shí)指定編譯器這段程序會(huì)在0x0c000000地址上運(yùn)行,因此全局變量和全局函數(shù)指針就會(huì)從0x0c000000上開始分配地址,此時(shí)如果你把這段程序燒錄到0x0c000000地址上運(yùn)行,變量的訪問和指令存取不會(huì)有人任何問題,但是如果你將程序下載到0x00000000上運(yùn)行時(shí),在程序會(huì)在訪問全局變量時(shí),實(shí)際上這個(gè)變量地址分配的地址是0x00000001但是,因?yàn)槟憔幾g是連接地址不是0x00000000所以程序會(huì)到0x0c000001去讀取這個(gè)變量,此時(shí)就會(huì)讀到一個(gè)錯(cuò)誤的值。對(duì)于函數(shù)指針也是相同的道理,但此時(shí)指令就跑飛了。
ARM處理器上的用處(相對(duì)跳轉(zhuǎn)和絕對(duì)跳轉(zhuǎn))
絕對(duì)跳轉(zhuǎn):就是執(zhí)行了這一條指令之后就會(huì)跳轉(zhuǎn)到絕對(duì)跳轉(zhuǎn)的指令中的地址去執(zhí)行。
相對(duì)跳轉(zhuǎn):從當(dāng)前地址偏移一定的偏移地址去執(zhí)行一個(gè)程序。
將被編譯到0xC0000000地址的代碼放到0x00000000地址開始執(zhí)行,如果它們只使用順序執(zhí)行或者相對(duì)跳轉(zhuǎn)執(zhí)行方式就可以正常運(yùn)行(未使用全局變量和全局函數(shù)指針),但如果使用了絕對(duì)尋址,那么程序就跑飛了。
我們參照下面這段偽代碼來說明這個(gè)情況。
在編譯、鏈接的時(shí)候,這段程序被告知放在0xC0000000地址空間,編譯后燒錄到0x00000000結(jié)果在存儲(chǔ)設(shè)備中的存放結(jié)果為(每條指令以4字節(jié)計(jì)算):
指令地址 指令編號(hào) 指令功能 下條指令地址0x00000000 指令1: 順序執(zhí)行 當(dāng)前地址+4 0x00000004 指令2: 順序執(zhí)行 當(dāng)前地址+4 0x00000008 指令3: 相對(duì)跳轉(zhuǎn)到指令5 當(dāng)前地址+8 0x0000000C 指令4: 順序執(zhí)行 當(dāng)前地址+4 0x00000010 指令5: 順序執(zhí)行 當(dāng)前地址+4 0x00000014 指令6: 絕對(duì)跳轉(zhuǎn)到指令8 0xC000001C 0x00000018 指令7: 順序執(zhí)行 當(dāng)前地址+4 0x0000001C 指令8: 順序執(zhí)行 當(dāng)前地址+4程序從0x00000000開始運(yùn)行直到第五條指令都是不會(huì)出錯(cuò)的,但是當(dāng)執(zhí)行完指令6后程序就會(huì)跑飛了,因?yàn)橹噶?是一條絕對(duì)跳轉(zhuǎn)的指令但0xC000001C空間沒有代碼,這樣程序就跑飛了。但當(dāng)這段程序被放在0xC0000000起始空間時(shí),開始執(zhí)行指令1,然后采用相對(duì)尋址的方法就可以運(yùn)行到指令6,在指令6執(zhí)行時(shí)執(zhí)行絕對(duì)尋址的方法從0xC0000014正確跳轉(zhuǎn)到指令8所在的0xC000001C位置,這段代碼運(yùn)行正常。(參考博客:http://blog.sina.com.cn/s/blog_908da74601011bg6.html)
如圖:
MDK編譯后的STM32工程 map文件簡(jiǎn)單分析
只看map文件中有用的部分:
Code為程序代碼部分
RO-data 表示 程序定義的常量const temp;
RW-data 表示 已初始化的全局變量
ZI-data 表示 未初始化的全局變量
Program Size: Code="18248" RO-data=320 RW-data=260 ZI-data=3952
Code, RO-data,RW-data ............flash
RW-data, ZIdata...................RAM (內(nèi)存)
?
存儲(chǔ)Size:
RO size: Code + RO_data
RW size: RW_data + ZI_data
ROM (minimum)size = Code + RO_data + RW_data (即燒/下載程序到FLASH/ROM時(shí),所占用的最小空間)
Total ROM Size (Code + RO Data + RW Data)這樣所寫的程序占用的ROM的字節(jié)總數(shù),也就是說程序所下載到ROM flash 中的大小。為什么Rom中還要存RW,因?yàn)榈綦姾驲AM中所有數(shù)據(jù)都丟失了,每次上電RAM中的數(shù)據(jù)是被重新賦值的,每次這些固定的值就是存儲(chǔ)在Rom中的,為什么不包含ZI段呢,是因?yàn)閆I數(shù)據(jù)都是0,沒必要包含,只要程序運(yùn)行之前將ZI數(shù)據(jù)所在的區(qū)域一律清零即可。包含進(jìn)去反而浪費(fèi)存儲(chǔ)空間。
RAM size: RW Data + ZI Data (即程序運(yùn)行的時(shí),RAM使用的空間)
一個(gè)ARM程序包含3部分:RO段,RW段和ZI段
RO是程序中的指令和常量
RW是程序中的已初始化變量
ZI是程序中的零初始化的變量
由以上3點(diǎn)說明可以理解為:
RO就是readonly,
RW就是read/write,
ZI就是zero
完事,今天好冷哎!
轉(zhuǎn)載于:https://www.cnblogs.com/w-smile/p/10073790.html
總結(jié)
以上是生活随笔為你收集整理的编译过程中的链接地址对最终编译镜像文件的影响的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用memocache
- 下一篇: bootstrap-table文档