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