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