linux系統下程式編譯過程

2021-08-08 13:52:16 字數 1693 閱讀 5625

編譯過程

在linux系統下,使用gcc可以完成整個編譯過程,gcc是什麼?

它並不是乙個編譯器,而是乙個驅動程式。編譯過程中每個環節由具體的元件負責,編譯過程由cc1負責、彙編過程由as彙編器負責、鏈結過程由ld負責。

預編譯(預處理)

我們在編譯程式時可以通過加 -e選項告訴編譯器僅作預處理

gcc -e ***.c -o ***.i

(1)檔案包含

檔案包含命令指示預處理器將原始檔的內容全部複製到當前原始檔中。

(2)巨集定義

巨集可以提高程式的通用性和易讀性,減少不一致性和輸入錯誤,便於維護。

在預處理過程中,預編器將巨集名替換為具體的值。

(3)條件編譯

在大多數情況下,源程式中所有的語句都參加編譯,但有的時候使用者希望按照一定的條件去編譯源程式的不同部分,這時可以使用條件編譯。

編譯編譯程式對預處理過的結果進行詞法分析、語法分析、語義分析,然後產生中間**,並對中間**進行優化,目標是使最終生成的可執行**執行時間更短、占用的空間更小,最後生成相應的彙編**。

可以使用gcc -s ***.c指定編譯過程只進行編譯,不進行彙編和鏈結。

frame pointer和base pointer均指向棧幀的底部,在ia32(intel architecture 32bit)中,通常使用暫存器ebp儲存這個位置。在組合語言中,在函式的開頭和結尾處分別會插入一小段**,分別稱為prologue和epilogue。

prologue儲存主調函式的frame pointer,這是為了在子函式呼叫結束後,恢復主調函式的棧幀。同時為子函式準備棧幀。其主要操作包括:

1.儲存主調函式的frame pointer,將儲存在暫存器ebp的frame pointer壓棧。在退出子函式時可以從棧中恢復主調函式的frame pointer。

2.將esp賦值給ebp,即將子函式的frame pointer指向主調函式的棧頂。

3.修改棧頂指標esp,為子函式的本地變數分配棧空間。

main函式並不是程式中第乙個呼叫的函式,main函式也是乙個被調函式,其也有棧幀。程式中第乙個被呼叫的函式_start也會自己模擬乙個棧幀。

epilogue功能與prologue相反,其主要操作包括:

將棧指標esp指向當前子函式的棧幀的frame pointer,也就是說,指向當前棧幀的棧底,而這個位置,恰好是prologue儲存的主調函式的frame pointer。然後,通過指令pop將主調函式的frame pointer彈出到ebp中。

2.將呼叫子函式時call指令壓棧的返回位址從棧頂pop到eip中,並跳轉到eip處繼續執行。如此,cpu就返回到主調函式繼續執行。

彙編

鏈結

如果在鏈結過程中有靜態庫,在鏈結靜態庫時,並不是將整個靜態庫中包含的目標檔案全部複製乙份到最終的可執行檔案中,而是僅僅鏈結庫中使用的目標檔案。

動態庫在可執行檔案中不會有任何副本

1. 動態載入庫需要知道可執行程式依賴的動態庫,這樣在載入可執行程式時才能載入其依賴的動態庫。所以,在鏈結時,鏈結器將根據可執行程式引用的動態庫中的符號的情況在dynamic段中記錄可執行程式所依賴的動態庫。

2.鏈結器需要在重定位表中建立重定位記錄,這樣當動態鏈結器載入動態庫時,將依據重定位記錄動態庫引用的這些外部符號。

Linux下程式的編譯過程

編譯器使用gcc編譯器 編譯的過程如下 1.預處理 gcc e test.c o test.i 可以使用cat命令檢視 cat test.i 過程包括 展開巨集定義 define 將 include包含的檔案插入到該預編譯指令所在的位置 處理條件預編譯指令 if ifdef elif else en...

Linux下程式編譯鏈結過程

在linux下使用gcc將原始碼 c檔案 編譯成可執行檔案的過程可以分解為4個步驟,分別是預處理 prepressing 編譯 compilation 彙編 assembly 鏈結 linking i命令 gcc e hello.c o hello.i e 可以使編譯器在預處理完成後就停止編譯 o ...

linux系統下通過GCC編譯C C 程式

在這裡插入描述 三 gcc編譯c c 的過程 通過命令gcc v檢視當前的gcc版本 gcc v如下所示 當出現如下問題 command gcc not found,but can be installed with sudo apt install gcc 解決辦法 通過sudo apt inst...