理解編譯器在編譯過程中做了什麼

2021-08-15 04:00:08 字數 1561 閱讀 7457

今年開了作業系統課,課上老師提了乙個問題:從乙個儲存程式**的文字檔案到可執行的程式,編譯器做了啥?由於之前買過《深入了解計算機系統》這本書,剛買來時受熱就翻了其中一部分章節,其中就有講到上述所問的講解,索性就參考其上的講解寫出來

我會以乙個hello.c的c程式貫穿整個文章,具體**如下

#include

int main(int argc,char **argv)

該程式通過編譯器編譯生成hello程式,其執行結果如下 

那麼此程式從儲存它的文字檔案到可執行程式hello的中間編譯器究竟做了啥,不說話先上圖了

由上圖可知gcc編譯器驅動程式在讀取了hello.c檔案之後,把它翻譯成了乙個可執行**。此過程共經歷了4個階段的程式,分別是預處理器,編譯器,彙編器,鏈結器,此4個截斷程式一起構成了編譯系統。接下來我就為大家詳細說明以下此4個階段程式各自的具體工作

預處理器會將以字元#開頭的語句,修改為原始的c程式,比如hello.c中的#include

gcc -e hello.c -o hello.i
用vim開啟hello.i檔案之後如下圖 

這是檔案開頭

這是檔案結尾處

我想大家一定會驚訝的發現乙個簡簡單單的hello,world程式竟然會平白無辜的增加了800多行,沒錯這就是預處理器幹的,它將程式中以#開頭的stdio.h檔案的內容都加了進來 

需要強調的是,經預處理器的檔案是文字檔案

編譯器會將上文中提到的hello.i(預編譯好的檔案)近一步翻譯成儲存組合語言的文字,其字尾會變為.s 

我們可以通過如下方式將hello.c編譯成.s檔案

gcc -s hello.c -o hello.s
開啟hello.s檔案如下圖 

可以看到裡面的**變為了彙編** 

需要注意的是.s檔案依然是文字檔案

彙編器會將上述的hello.s檔案翻譯成機器語言指令,並把這些指令打包成一種叫做可重定位目標程式的格式並將結果儲存在新生成的二進位制檔案hello.o中

我們的程式hello中呼叫了printf函式,而printf函式存在於由c標準庫提供的名為printf.o的單獨預編譯好了的目標檔案中,所以我們要呼叫printf函式,就得通過鏈結器,使其通過它自己的方式將hello.o和printf.o這倆個檔案合併在一起,經過合併後的檔案就是可執行的hello檔案了

原始檔在編譯器中的處理過程

預處理 1.只進行預處理操作 gcc e demo.c demo2.i 大於號的作用是把進行預處理操作後生成的.i檔案放到大於號後面的檔案裡面,稱作重定向。經過預處理之後的檔案字尾名為.i 2.預處理做的事情包括 標頭檔案展開 巨集替換 條件編譯 條件編譯在實際應用中非常多,通過條件編譯可以選擇編譯...

c 編譯器編譯過程

編譯過程 編譯過程分為四步 預處理 編譯 彙編 連線 1.預處理 預處理主要處理原始檔中的 include define 等預處理等命令 預處理主要完成的工作有 參考 程式設計師的自我修養 1 刪除 define,展開巨集 2 處理條件編譯指令。預處理程式先判斷條件,再根據條件修改源 3 刪除注釋 ...

方舟編譯器編譯過程

開發環境推薦ubuntu16.04 sudo apt get y install openjdk 8 jdk git core gnupg flex bison gperf build essential zip curl zlib1g dev libc6 dev i386 lib32ncurses...