但是也有一種特別的指令他可以跟指定的鏈結位址沒有關係,這些**不管放在**都可以正常執行。
分析:
在linux中的應用程式:gcc hello.c -o hello
bootloader必須大於16kb小於96kb,假定為80kb。啟動過程如下:開機上電後bl0執行,bl0載入外部啟動裝置中的bootloader的前16kb(bl1)到sram中執行,bl1執行後會載入bl2到(80-16=64kb)到sram中執行,bl2執行時會初始化ddr並且將os搬到ddr中執行,啟動完成。
uboot實際使用方式:
uboot大小隨意,假定為200kb,啟動過程:先開機上電後bl0執行,bl0會載入外部啟動裝置中的uboot的前16kb到sram執行,bl1執行時會初始化ddr,然後將整個uboot搬運到ddr中,然後用一句長跳轉指令從sram直接跳轉到ddr中繼續執行uboot直到uboot完全啟動。uboot啟動後在命令列中啟動os
預編譯:預編譯器執行。譬如c中的巨集定義就是由預編譯處理器處理,注釋等也是由預編譯器處理的
編譯:編譯器來執行。把原始碼.c .s編譯成機器碼
strip:strip是把可執行程式中的符號給拿掉,以節省空間(debug版本和release版本)
objcopy:由可執行程式生成可燒錄的映象bin檔案
段是程式的一部分,我們把整個程式的所有東西分成了乙個個段,給每個段起乙個名字,然後再鏈結時可以用和這個名字來指示這些段
段名分為2種:一種是編譯器聯結器內部定好的,一種是程式設計師自己指定的,自定義的段名
先天性段名:
後天性段名:
段名由程式設計師自己定義,段的屬性和特徵也由程式設計師自己定義。
分析一些問題,跟這裡結合,然後試圖明白一些本質
鏈結指令碼就是乙個規則檔案,他是程式設計師用來指揮鏈結器用來工作的。鏈結器會參考鏈結指令碼並且使用其中規定的規則來處理.o檔案中的那些段,將其鏈結成可執行程式。
sections{}這個是整體鏈結指令碼
. 點號在鏈結指令碼中代表當前位置
= 等號代表賦值
sections.data :
bss_start =.;
.bss :
bss_end =.;
}
我們把鏈結位址設定為0xd0024000時,隱含意思就是這段**將來必須放在0xd0024000位置才能正確執行。
如果實際執行位址不是這個位址就要出事(除非**是位置無關碼)。所以重定位**的作用就是在pic執行前(**中第一句位置有關碼執行前)必須將整個**搬移到0xd0024000去執行。
長跳轉:首先這局**是一句跳轉指令(arm的跳轉指令就是類似於分支指令b、bl等作用指令),跳轉指令通過pc(r15)賦乙個新值來完成**段的跳轉執行。長跳轉指的是跳轉到的位址和當前位址差異比較大,跳轉的範圍比較寬廣。
重定位和鏈結指令碼
重定位實際就是在執行位址處執行一段位置無關碼pic,讓這段pic 也就是重定位 從執行位址處把整個程式映象拷貝乙份到鏈結位址處,完了之後使用一句長跳轉指令從執行位址處直接跳轉到鏈結位址處去執行同乙個函式,這樣就實現了重定位之後的無縫連線。鏈結位址 鏈結時指定的位址 指定方式為 makefile中用 ...
重定位引入和鏈結指令碼
1 乙個事實 大部分指令是位置有關編碼 位置無關編碼 pic,position independent code 彙編原始檔被編碼成二進位制可執行程式時編碼方式與位置 記憶體位址 無關。位置有關編碼 彙編原始碼編碼成二進位制可執行程式後和記憶體位址是有關的。我們在設計乙個程式時,會給這個程式指定乙個...
鏈結指令碼與重定位
一 位置有關 和位置無關 以前,我們編寫程式的時候,根本不知道還有位置有關 和位置無關 不知道 的執行居然和 的鏈結位址有關,當然也不知道鏈結位址是什麼,但是在linux的學習中,這些都是必須的。舉個例子 我們在設計乙個程式的時候,就必須給這個程式指定乙個執行位址 這個指定的執行位址就是鏈結位址 這...