Linux程式編譯過程

2020-08-08 21:52:49

其餘相關內容可參考個人部落格

簡介

該部分內容僅作概念上的介紹,具體細節請參照《程式設計師的自我修養–鏈接、裝載與庫習》進行學習,以下筆記也是書中相關內容

編譯過程大體可分爲4個過程,預處理(preprocessing)、編譯(compiliation)、彙編(assembly)和鏈接(linking)

使用 gcc 命令不跟任何的選項的話,會預設執行預處理、編譯、彙編、鏈接這整個過程,如果程式沒有錯,就會得到一個可執行檔案,預設爲a.out

-E選項:提示編譯器執行完預處理就停下來,後邊的編譯、彙編、鏈接就先不執行了。

-S選項:提示編譯器執行完編譯就停下來,不去執行彙編和鏈接了。

-c選項:提示編譯器執行完彙編就停下來。

所以,這三個選項相當於是限定了編譯器執行操作的停止時間,而不是單獨的將某一步拎出來執行

預處理

  • 將所有的#define刪除,並且展開所有的宏定義
  • 處理所有的條件編譯指令,比如#if、#ifdef、#elif、#else、#endif
  • 處理#include預編譯指令,將被包含的標頭檔案插入到該編譯指令的位置。(這個過程是遞回進行的,因爲被包含的檔案可能還包含了其他檔案)
  • 刪除所有的註釋///* */
  • 新增行號和檔名標識,方便後邊編譯時編譯器產生偵錯用的行號心意以及編譯時產生編譯錯誤或警告時能夠顯示行號。
  • 保留所有的#pragma編譯指令,因爲編譯器需要使用它們。

編譯

編譯過程是整個程式構建的核心部分,就是把預處理完的檔案進行一系列詞法分析、語法分析、語意分析以及優化後生成相應的彙編程式碼檔案
該部分在此處不作詳細介紹

彙編

彙編過程呼叫匯編器as來完成,是用於將彙編程式碼轉換成機器可以執行的指令,每一個彙編語句幾乎都對應一條機器指令。

反彙編的含義是將機器碼轉換成彙編程式碼。

鏈接

鏈接的主要內容就是將各個模組之間相互參照的部分正確的銜接起來。它的工作就是把一些指令對其他符號地址的參照加以修正。鏈接過程主要包括了地址和空間分配、符號決議和重定向

  • 符號決議:有時候也被叫做符號系結、名稱系結、名稱決議、或者地址系結,其實就是指用符號來去標識一個地址。

  • 重定位:重新計算各個目標的地址過程叫做重定位

該部分內容在後續部落格中單獨講解