計算機程序編譯過程

                                          計算機程序編譯過程

引言:在大學學習了很多種語言:C , C++ ,java ,matlab 等,對於計算機中的一個程序是怎樣運行的很是陌生又因爲考試要用關於這方面的知識,在百度上發現一篇文章感覺很不錯,在這裏分享給大家,原鏈接https://www.jianshu.com/p/04335d843ec7

計算機程序編譯過程分爲4個步驟:

  • 預處理
  • 編譯
  • 彙編
  • 鏈接

預處理

 

$gcc -E hello.c -o hello.i

 

$cpp hello.c > hello.i

預編譯過程主要:

  1. 處理預編譯指令,例如 #define,#if,#ifdefine 等。
  2. 將 #include 包含文件插入到該預編譯指令的位置
  3. 刪除所有的注析 // 、/**/

編譯

 

$gcc –S hello.i –o hello.s

 

$gcc –S hello.c –o hello.s

編譯代表了一整個過程:

  • 詞法分析
  • 語法分析
  • 語義分析
  • 源代碼優化
  • 代碼生成
  • 目標代碼優化

詞法分析

掃描字節序併產生記號。
詞法分析產生的記號一般可以分爲如下幾類:關鍵字、標識符、字面量(包含數字、字符串等)和特殊符號(如加號、等號)。

語法分析

語法分析器(Grammar Parser)將對由掃描器產生的記號進行語法分析,從而產生語法樹(Syntax Tree)。由語法分析器生成的語法樹就是以表達式(Expression)爲節點的樹。

語義分析

語法分析僅僅是完成了對表達式的語法層面的分析,但是它並不瞭解這個語句是否真正有意義。
編譯器所能分析的語義是靜態語義(Static Semantic),所謂靜態語義是指在編譯期可以確定的語義,與之對應的動態語義(Dynamic Semantic)就是只有在運行期才能確定的語義。
靜態語義通常包括聲明和類型的匹配,類型的轉換。

動態語義和靜態語義?

比如將一個浮點型賦值給一個指針的時候,語義分析程序會發現這個類型不匹配,編譯器將會報錯。動態語義一般指在運行期出現的語義相關的問題,比如將0作爲除數是一個運行期語義錯誤。

中間語言生成

中間代碼使得編譯器可以被分爲前端和後端。編譯器前端負責產生機器無關的中間代碼,編譯器後端將中間代碼轉換成目標機器代碼。這樣對於一些可以跨平臺的編譯器而言,它們可以針對不同的平臺使用同一個前端和針對不同機器平臺的數個後端。

目標代碼生成與優化

代碼級優化器產生中間代碼標誌着下面的過程都屬於編譯器後端。編譯器後端主要包括代碼生成器(Code Generator)和目標代碼優化器(Target Code Optimizer)。
代碼生成器將中間代碼轉換成目標機器代碼,這個過程十分依賴於目標機器。

對於上面例子中的中間代碼,代碼生成器可能會生成下面的代碼序列

 

movl index, %ecx        ; value of index to ecx
addl $4, %ecx           ; ecx = ecx + 4
mull $8, %ecx             ; ecx = ecx * 8
movl index, %eax        ; value of index to eax
movl %ecx, array(,eax,4)  ; array[index] = ecx

彙編

 

$as hello.s –o hello.o

 

$gcc –c hello.c –o hello.o

彙編器(as)將彙編代碼翻譯成機器語言指令,把這些指令打包成一種叫做可重定位目標程序(relocatable)的格式,並將結果保持在目標文件 hello.o 中。hello.o 是一個二進制文件。

鏈接

 

$ld -static /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i486-linux-gnu/4.1.3/crtbeginT.o -L/usr/lib/gcc/i486-linux-gnu/4.1.3 -L/usr/lib -L/lib hello.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/i486-linux-gnu/4.1.3/crtend.o /usr/lib/crtn.o

鏈接階段最重要的工作就是重定位,將所有的目標文件都鏈接起來,在 #include 文件中的函數聲明原本只會生成一個沒有跳轉地址的指令,重定位的工作在其他目標文件中找到這些目標地址,並把地址填補進去。

鏈接分爲靜態鏈接和動態鏈接,也就是我們通常說的私有對象和共享對象。這裏得展開另外一篇來講了,內容太多。

鏈接就像將所有的組件合成一起,組成一個整體。



作者:Abson在簡書
鏈接:https://www.jianshu.com/p/04335d843ec7
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章