對于程序員來說編譯器是非常熟悉的,每天都在用,但是當你在點擊“Run”這個按鈕或者執行編譯命令時你知道編譯器是怎樣工作的嗎?
這篇文章就為你解答這個問題。
編譯器就是一個普通程序,沒什么大不了的
什么是編譯器?
編譯器是一個將高級語言翻譯為低級語言的程序。
首先我們一定要意識到編譯器就是一個普通程序,沒什么大不了的。
在沒有弄明白編譯器如何工作之前你可以簡單的把編譯器當做一個黑盒子,其作用就是輸入一個文本文件輸出一個二進制文件。
基本上編譯器經過了以下幾個階段,等等,這句話教科書上也有,但是我相信很多同學其實并沒有真正理解這幾個步驟到底在說些什么,為了讓你徹底理解這幾個步驟,我們用一個簡單的例子來講解。
假定我們有一段程序:
while (y < z) { int x = a + b; y += x;}
那么編譯器是怎樣把這一段程序人類認識的程序轉換為CPU認識的二進制機器指令呢?
提取出每一個單詞:詞法分析
首先編譯器要把源代碼中的每個“單詞”提取出來,在編譯技術中“單詞”被稱為token。其實不只是每個單詞被稱為一個token,除去單詞之外的比如左括號、右括號、賦值操作符等都被稱為token。
從源代碼中提取出token的過程就被稱為詞法分析,Lexical Analysis。
經過一遍詞法分析,編譯器得到了以下token:
T_While whileT_LeftParen (T_Identifier yT_Less
就這樣一個磁盤中保存的字符串源代碼文件就轉換為了一個個的token。
這些token想表達什么意思:語法分析
有了這些token之后編譯器就可以根據語言定義的語法恢復其原本的結構,怎么恢復呢?
原來,編譯器在掃描出各個token后根據規則將其用樹的形式表示出來,這顆樹就被稱為語法樹。
語法樹是不是合理的:語義分析
有了語法樹后我們還要檢查這棵樹是不是合法的,比如我們不能把一個整數和一個字符串相加、比較符左右兩邊的數據類型要相同,等等。
這一步通過后就證明了程序合法,不會有編譯錯誤。
根據語法樹生成中間代碼:代碼生成
語義分析之后接下來編譯器遍歷語法樹并用另一種形式來表示,用什么來表示呢?那就是中間代碼,intermediate representation code,簡稱IR code。
上述語法樹可能就會表示為這樣的中間代碼:
Loop: x = a + b y = x + y _t1 = y < z if _t1 goto Loop
怎么樣,這實際上已經比較接近最后的機器指令了。
只不過這還不是最終形態。
中間代碼優化
在生成中間代碼后要對其進行優化,我們可以看到,實際上可以把x = a + b這行代碼放到循環外,因為每次循環都不會改變x的值,因此優化后就是這樣了:
x = a + bLoop: y = x + y _t1 = y < z if _t1 goto Loop
中間代碼優化后就可以生成機器指令了。
代碼生成
將上述優化后的中間代碼轉換為機器指令:
add $1, $2, $3Loop: add $4, $1, $4 slt $6, $1, $5 beq $6, loop
最終,編譯器將程序員認識的代碼轉換為了CPU認識的機器指令。
總結
注意這篇簡短的講解不希望給大家留下這樣的印象,那就是編譯器是很簡單的,恰恰相反,現代編譯器是非常智能并且極其復雜的,絕不是短短一篇文章就能講清楚的,能實現一個編譯器是困難的,實現一個好的編譯器更是難上加難。
本文的目的旨在以極簡的方式描述編譯器的工作原理,這樣你就不用把編譯器當做一個黑盒了,希望這篇文章能對你有所幫助。
編輯:lyn
-
編譯器
+關注
關注
1文章
1623瀏覽量
49108
原文標題:編譯器是如何工作的
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論