章節目錄
- 靜態鏈接
– 編譯和鏈接
– 目標檔案
– 靜態鏈接
– windows COFF - 裝載和動態鏈接
– 可執行檔案的裝載與行程
– 動態鏈接
– Linux共享庫的組織
– Windows下的動態鏈接 - 庫與運行庫
– 記憶體
– 運行庫
– 系統呼叫與API
– 運行庫實作
一、編譯和鏈接
從hello_world.c 到可執行檔案(executable file),經歷了編譯、鏈接程序,這個程序分為4步:
- 預處理 Prepressing
- 編譯 Compilation, Compile
- 匯編 Assembly, Assemble
- 鏈接 Linking, Link
1.1 預處理
處理“#”開始的預編譯命令,例如包含頭檔案、宏的文本替換、#if 條件預處理、刪掉注釋,除錯器需要的檔案、行號資訊,也在此時加入,
1.2 編譯
預處理之后的檔案,進行
- 詞法分析
- 語法分析
- 語意分析
- 優化
- 生成匯編代碼檔案
詞法分析
處理關鍵字、識別符號(變數名)等
語法分析
是不是符合語法,例如:分號;,括號{},運算子(運算元,優先級)
語意分析
分析if,for, while,等邏輯,變數型別的匹配、轉換,
優化
好的編譯器會對代碼進行優化,
例如,刪去明顯不可能執行的if分支,例如if(char > 1000),而char 范圍在0-255,
例如,a = 2+3; 這樣的陳述句很明顯可以優化成a=5;
生成匯編代碼檔案
高級語言–>匯編語言
1.3 匯編
將匯編檔案轉變為機器碼(指令),
因為不同的CPU都有自己的指令體系,是由芯片廠家制定的,這就是CPU架構的概念,例如ARM架構,例如同樣的MOV R0 R1; 翻譯成ARM指令或Thumb指令的二進制值不同,指令,可以理解為集成電路實作的switch陳述句,一個指令進一個case分支,
所謂集成電路(IC)設計,就是用晶體管組成電路,實作選擇、回圈、順序等邏輯,設計時用的是HDL(hardware description language)硬體描述語言,和C語言類似,
1.4 鏈接
直到匯編完成,都是每個c檔案生成單獨的二進制檔案(.o檔案),c檔案之間互相呼叫關系還沒有完成,連接器就是把.o檔案通過他們的關系鏈接起來,最終生成.out檔案
(.out是Linux的可執行檔案(executable file)的格式,Window中是.exe檔案)
例如a.c中的main()函式呼叫了b.c中的add(x,y)函式,那么鏈接之前,a.c并不知道add函式存不存在,在什么位置,于是把add函式的入口地址空著(默認0),等聯結器找到add函式,再把地址填到這里,
在簡單的嵌入式系統中,這個地址就是實際的物理地址,嵌入式系統廠家,一般也不會把RAM地址設為0x0,例如是0x1000,那就需要給聯結器提供這些資訊,
1.5 總結
這樣看來一個好的IDE(Intergrated Develop Environment),應該包括:
- 編輯器
寫代碼,好的編輯器還能給豐富的提示、語法檢查等功能, - 編譯器(廣義)
把代碼生成可執行檔案,包括:前處理器,編譯器,聯結器,好的編譯器,會在編譯出錯時給出充分的錯誤資訊, - 除錯器
程式運行出問題時debug,一般程序:設斷點,控制執行,分析變數值,手動修改變數值,找出bug原因,好的除錯器,能提供方便、豐富的除錯工具,展示充分的資訊,
嵌入式系統因為其特殊性,一般其除錯器需要硬體聯調,需要有硬體溝通PC和待除錯設備,例如JTAG(J-link),SWD等,
在復雜工程中,聯結器會需要鏈接腳本ld檔案,或者撰寫make檔案來管理工程,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/201616.html
標籤:其他
下一篇:程式員笑話二十八
