- 預處理:處理宏、包含頭文件、條件編譯等。
- 編譯:將預處理後的代碼轉換為匯編代碼,構建符號表。
- 組譯:將匯編代碼轉換為目標代碼,分配偏移量。
- 連結:將所有目標文件連結,解決符號引用,分配最終內存地址。
這些步驟和工具協同工作,確保最終的可執行文件能夠在計算機的記憶體中正確運行。
步驟與相關的系統工具程式
-
預處理(Preprocessing)
- 工具程式:預處理器(如 cpp)
- 功能:預處理器處理所有以 # 開頭的預處理指令(如 #include, #define),展開宏,包含頭文件,並處理條件編譯指令。
- 輸出:預處理過的代碼,通常是 .i 文件。
-
編譯(Compilation)
- 工具程式:編譯器(如 gcc,clang)
- 功能:編譯器將預處理過的 C 語言代碼轉換為中間的匯編代碼。這個步驟包括語法分析、語義分析、優化和代碼生成。
- 輸出:匯編代碼,通常是 .s 文件。
-
組譯(Assembly)
- 工具程式:組譯器(如 as)
- 功能:組譯器將匯編代碼轉換為目標代碼(機器碼)。這一步生成二進制的目標文件。
- 輸出:目標代碼,通常是 .o 文件。
-
連結(Linking)
- 工具程式:連結器(如 ld)
- 功能:連結器將一個或多個目標文件和庫文件連結起來,生成最終的可執行文件。連結器解析符號,解決外部符號引用,並分配記憶體地址。
- 輸出:可執行文件,通常是 .exe(在 Windows 中)或無擴展名的文件(在 Unix/Linux 中)。
識別碼(identifier)轉換為記憶體位址的過程
-
預處理階段
- 識別碼(如變量名、函數名)在這一階段只是文本,預處理器不會對其進行任何轉換或處理。
-
編譯階段
- 編譯器在這一階段會進行語法分析和語義分析,構建抽象語法樹(AST)和符號表。符號表中記錄了所有識別碼的相關信息,如變量名、類型、作用域等。
- 優化過程中,編譯器可能會進行代碼優化,但識別碼本身還未轉換為具體的記憶體地址。
- 最終,編譯器將識別碼轉換為匯編指令中的符號名,但這些符號名還沒有具體的內存地址。
-
組譯階段
- 組譯器將匯編代碼轉換為機器碼,並為每個符號分配偏移量,但這些偏移量是相對於各自的目標文件的。
- 在目標文件中,識別碼轉換為符號表中的符號,這些符號具有各自的偏移量,但具體的內存地址要到連結階段才能確定。
-
連結階段
- 連結器將所有目標文件和庫文件連結起來,解決所有符號引用,並為每個符號分配最終的內存地址。
- 連結器通過符號解析過程,將識別碼(符號名)轉換為具體的記憶體地址,並更新所有目標文件中的符號引用,使它們指向正確的內存地址。