構建C程序須要4個步驟,分別使用4個工具完成: preprocessor, compiler, assembler, and linker.四步完成後生成一個可執行文件。數據庫
第一步,預處理. 這一步處理 頭文件、條件編譯指令和宏定義。編程
第二步,編譯. 將第一步產生的文件連同其餘源文件一塊兒編譯成彙編代碼。數組
第三步,彙編。將第二步產生的彙編源碼轉換爲 object file.編程語言
第四步,連接. 將第三步產生的一些object file 連接成一個可執行的文件。工具
【龍書】編譯原理(第二版)學習與理解:性能
①編譯器首先也是一種電腦程序。它會將用某種編程語言寫成的源代碼(原始語言),轉換成另外一種編程語言(目標語言)。學習
②高級計算機語言便於人編寫,閱讀,維護。低階機器語言是計算機能直接解讀、運行的。編譯器主要的目的是將便於人編寫,閱讀,維護的高級計算機語言所寫做的源代碼,翻譯爲計算機能解讀、運行的低階機器語言的程序。編譯器將原始程序(Source program)做爲輸入,翻譯產生使用目標語言(Target language)的等價程序。源代碼通常爲高階語言 (High-level language), 如 Pascal、C、C++、C# 、Java 等,而目標語言則是彙編語言或目標機器的目標代碼(Object code),有時也稱做機器代碼(Machine code)。優化
一開始看比較容易被各類詞法,語法等弄得頭大。其實計算機的所謂語法,類比一下天然語言,無非也同樣是語言的結構方式。包括詞的構成和變化, 詞組和句子的組織。無外乎主謂賓這樣的一些規則或者結構來表達一個意思。爲了後續學習的順利性,這裏有必要先把各類術語搞清楚。spa
編譯器的第一個步驟稱爲詞法分析或掃描。它識別出一個個的單詞(亦稱單詞符號或簡稱符號),如基本字(begin、end、if、for、while),標識符、常數、運算符和界符(標點符號、左右括號)。單詞符號是語言的基本組成成分,是人們理解和編寫程序的基本要素。識別和理解這些要素無疑也是翻譯的基礎。如同將英文翻譯成中文的情形同樣,若是你對英語單詞不理解,那就談不上進行正確的翻譯。在詞法分析階段的工做中所依循的是語言的詞法規則(或稱構詞規則)。描述詞法規則的有效工具是正規式和有效自動機。翻譯
詞法分析器讀入組成源程序的字符流,並將其組成有意義的詞素的序列。形如<token-name, attribute-value>這樣的詞法單元。(token-name是由語法分析使用的抽象符號,attribute-value是指向符號表中關於這個詞法單元的條目,符號表條目的信息會被語義分析和代碼生成步驟使用)
例如源程序包含以下賦值語句:position = initial + rate * 60
對其進行詞法分析:
抽象符號 |
詞素 |
標識符 id | position |
賦值運算符 = | = |
標識符 id | initial |
加法運算符 + | + |
標識符 id | rate |
乘法運算符 * | * |
整數 60 | 60 |
空格(分析器直接忽略) |
通過詞法分析以後,賦值語句的詞法單元序列:<id, 1> < = > <id, 2> < + > <id, 3> < * > <60>
圖1-1 一個賦值語句的翻譯
① 語法是語言學的一個分支,研究按肯定用法來運用的詞類、詞的屈折變化或表示相互關係的其餘手段以及詞在句中的功能和關係。包含詞的構詞、構形的規則和組詞成句的規則。
舉個例子:我是人;他學習漢語;你登山...........這樣的句子有千千萬萬。那麼人們會總結出來:主語+謂語+賓語 這樣的語法規則來。
因爲計算機的特殊性,所以計算機的語法邏輯性更強,更注重算術和表達式等, 因此就沒有那麼簡單的「主謂賓」,咱們看的更多的可能相似 x = y + 1,等;
② 文法:天然語言漢語中的意思1.法制;法規。 2.文章的做法。 3.語法。語言的結構方式。包括詞的構成和變化﹐詞組和句子的組織。文法即文章的書寫法規,通常用來指以文字、詞語、短句、句子的編排而組成的完整語句和文章的合理性組織。
文法即語言中的每一個句子能夠用嚴格定義的規則來構造.
編譯的第2個步驟稱爲語法分析或解析。語法分析器使用由詞法分析器生成的各詞法單元的第一個份量來建立樹形的中間表示。該中間表示給出了詞法分析產生的詞法單元的語法結構。經常使用的表示方法是語法樹,樹中每一個內部節點表示一個運算,而該節點的子節點表示運算的份量。
以上賦值語句表示成語法樹:
(數據的含義就是語義。簡單的說,數據就是符號。數據自己沒有任何意義,只有被賦予含義的數據纔可以被使用,這時候數據就轉化爲了信息,而數據的含義就是語義)
語義分析器使用語法樹和符號表中的信息來檢查源程序是否和語言定義的語義一致 。它同時收集類型信息,並存放在語法樹或符號表中,以便在中間代碼生成過程使用。
語義分析的一個重要部分就是類型檢查。好比不少語言要求數組下標必須爲整數,若是使用浮點數做爲下標,編譯器就必須報錯。再好比,不少語言容許某些類型轉換,稱爲自動類型轉換。
圖1-1中顯示了一個這樣的自動類型轉換,假設position,initial和rate已經被聲明爲浮點型,而詞素60是一個整數。語義分析器輸出中有一個inttofloat的額外節點,明確的把60轉換爲一個浮點數。
在進行了語法和語義的分析工做以後,編譯程序將源程序變成了一種內部表示形式,這種內部表示形式叫作中間語言或中間代碼, 也稱爲操做碼(Operate Code,opcode)。Opcode cache的目地是避免重複編譯,減小CPU和內存開銷。(注: 若是動態內容的性能瓶頸不在於CPU和內存,而在於I/O操做,好比數據庫查詢帶來的磁盤I/O開銷,那麼opcode cache的性能提高是很是有限的。可是既然opcode cache能帶來CPU和內存開銷的下降,這總歸是好事。)
在源程序翻譯成目標代碼的過程當中,一個編譯器可能構造出一個或多箇中間表示。這些中間表示能夠有多種形式。語法樹是一種中間表示形式,它們一般在語法分析和語義分析中使用。
在源程序的語法分析和語義分析完成以後(也會生成中間表示,區別語法樹),不少編譯器生成一個明確的低級的或類機器語言的中間表示。該中間表示有兩個重要的性質:1.易於生成;2.可以輕鬆地翻譯爲目標機器上的語言。
優化的任務在於對前段產生的中間代碼進行加工變換,以期在最後階段能產生出更爲高效(省時間和空間)或能耗更低的目標代碼。優化的主要方面有:公關子表達式的提取、循環優化、刪除無用代碼等等。有時,爲了便於「並行運算」,還能夠對代碼進行並行化處理。優化所依循的原則是程序的等價變換規則。
代碼生成以中間表示形式做爲輸入,並把它映射爲目標語言。若是目標語言是機器代碼,則必須爲每一個變量選擇寄存器或內存位置,中間指令則被翻譯爲可以完成相同任務的機器指令序列。
代碼生成的一個相當重要的方面是合理分配寄存器以存放變量的值。