1. 程式人生 > >軟件開發--鏈接器

軟件開發--鏈接器

定義 efi 區域 能夠 可執行程序 簡單的 嵌入式 環境 合並

一.鏈接器上

鏈接器的意義--鏈接器的主要作用是把各個模塊之間相互引用的部分處理好,使得各個模塊之間能夠正確的銜接
A.目標文件的秘密
1.各個段沒有具體的起始地址,只有段大小信息
2.各個標識符沒有實際地址,只有段中的相對地址
3.段和標識符的實際地址需要鏈接器具體確定
鏈接器的工作內容--將目標文件和庫文件合為最終的可執行程序
1.合並各個目標文件中的段(.text .data .bss)
2.確定各個段和段中標識符的最終地址(重定位)
運行的示例
技術分享圖片技術分享圖片技術分享圖片
根據之前一篇博客中的開發中的工具可以知道,同時使用nm命令可以看到標出紅線的都處在段標識U(未定義的標識中)
技術分享圖片技術分享圖片
而在對test.out文件進行nm命令後 可以看到之前未被定義的標識都處在相對於的標識段

Q:main()函數是第一個被調用執行的函數嗎?
默認情況下(gcc)
1.程序加載後,_start()是第一個被調用執行的函數
2._start()函數準備好參數後立即調用_libc_start_main()函數
3._libc_start_main()初始化運行環境後調用main()函數執行
示例及說明
技術分享圖片技術分享圖片
該示例就是通過簡單的一段程序來對main函數是否是第一個被調用執行的函數,通過上篇博客中的反編譯命令objdump使其生成result.txt文件來對匯編語言進行查看技術分享圖片技術分享圖片
可以看出對main進行查找時找到其地址值,然後將其地址值進行查找,發現在_start()函數中,此時進行的操作時將其地址值壓入堆空間中,可以看到在之後對_libc_start_main()函數進行了調用
_libc_start_main()函數的作用
1.調用_libc_csu_init()函數(完成必要的初始化操作)
2.啟動程序的第一個線程(主線程),main()為線程入口
3.註冊_libc_csu_fini()函數(程序運行終止時被調用)
技術分享圖片

Q:鏈接器根據什麽原則完成具體工作?
鏈接腳本的概念和意義
1.鏈接腳本用於描述鏈接器處理目標文件和庫文件的方式‘
a.合並各個目標文件
b.重定位各個段的起始地址
c.重定位各個符號的最終地址
技術分享圖片
示例
技術分享圖片技術分享圖片
上面的兩段程序分別為簡單的輸出程序和腳本程序,運行的結果如圖所示
技術分享圖片
發現在腳本語言中,出現了段錯誤的問題
註意事項:
1.各個段的鏈接地址必須符合具體平臺的規範
2.鏈接腳本中能夠直接定義標識符並指定存儲地址

3.鏈接腳本中能夠指定源代碼中標識符的存儲地址
技術分享圖片
運行objdump -h命令查看目標文件中的詳細段信息
技術分享圖片技術分享圖片技術分享圖片技術分享圖片
由該結果可以看出,出現段錯誤的原因,對其進行修改即可
技術分享圖片
技術分享圖片

**二.C語言在的內嵌匯編

A.內嵌匯編的語法格式

技術分享圖片
簡單示例:
技術分享圖片
技術分享圖片
在運行了反編譯objdump -S 命令後可以看到紅線標出的寄存器的關聯和動作**

編譯器的動作:
1.將result關聯到某個適合的寄存器
2.將input關聯到另一個適合的寄存器
3.通過寄存器間接操作變量
技術分享圖片
常用的限制符的說明
技術分享圖片

三 鏈接器下

課程實驗
1.編寫一個體積受限的可執行程序
2.通過makefile完成代碼編譯
3.運行後在屏幕打印數據
解決方案設計
1.通過內嵌匯編定義打印函數和退出函數(INT 80H)
2.通過鏈接腳本自定義入口函數(不依賴任何庫和GCC內置功能)
3.刪除可執行程序中的無用信息(無用段信息,調試信息,等)
工具
1.ld命令
a.GNU的鏈接器,將目標文件鏈接為可執行程序
b.GCC編譯器集中的一員,重要的幕後工作者
2.ld -static
a.-static表示ld使用靜態鏈接的方式來產生最終程序,而不是默認的動態鏈接方式
3.gcc -fno-builtin
-fno-builtin參數用於關閉GCC內置函數的功能
示例及運行結果
技術分享圖片技術分享圖片技術分享圖片
技術分享圖片
運行的結果如圖所示
技術分享圖片
小結:
1.鏈接器根據鏈接腳本中的描述完成具體的工作
2.鏈接腳本用於指定各個段的地址和標識符的地址
3.SECTIONS命令確定可執行程序中的段信息
4.MEMORY命令對存儲區域進行重定義
5.ENTRY命令指定可執行程序的入口函數
6.C語言中支持直接嵌入匯編語言進行編程
7.通過寄存器到變量的關聯完成匯編到c語言的交互
8.內嵌匯編代碼時,通過占位符指定交互的變量
9.限制符指示編譯器將適合的寄存器關聯到變量
10.通過內嵌匯編能夠直接使用系統服務
11.對於資源受限的嵌入式設備,需要考慮可執行程序的大小
12.通過內嵌匯編直接使用系統服務能夠避開相關庫的使用

軟件開發--鏈接器