1.1.1 摘要
我們知道電腦不能直接理解進階語言,它只能理解機器語言,所以我們必須要把進階語言翻譯成機器語言,這樣電腦才能執行進階語言編寫的程式,在接下來的博文中,我們將介紹非託管和託管語音的編譯過程。
1.1.2本文非託管環境的編譯過程(C/C++)
純C/C++的程式通常運行在一個非託管環境中,類是由標頭檔(.h)和實現檔案(.cpp)組成,每個類形成了一個單獨的編譯單元,當我們編譯器時,幾個基本組件會把我們的原始碼翻譯成二進位代碼,接下來我們通過以片說明非託管環境的編譯過程:
圖1 C/C++編譯過程
首先是前置處理器,如果在項目中有標頭檔和宏運算式,那麼它將負責包含標頭檔和翻譯所有的宏觀運算式。
接下來是編譯器,它不是直接產生二進位代碼,而是產生彙編代碼(.s),這基本上是所有現代的非結構化語言的共同基礎。
然後,組譯工具把彙編代碼翻譯成目標代碼(.o和.obj檔案,機器指令)。
最後連結器,它把所有彼此相關的目標檔案和產生的可執行檔或庫連結起來。
總而言之,在一般情況下,我們的代碼首先翻譯成彙編代碼,接著翻譯成機器指令(二進位代碼)。
什麼是宏?
在C/C++中,宏是預先處理指令,它有多種應用技術:包括預定義、建立關鍵字和條件編譯等等。在一般情況下,這些技術在C++中使用被認為是不好的做法,主要原因是有可能濫用C++提供的文法變化功能,甚至有可能在不知情情況下建立了非標準的語言,宏不遵循一般的原始碼編譯規則,由於它通過預先處理來處理,而不是編譯器。
託管環境的編譯過程(C#/Java)
在託管環境中,編譯的過程略有不同,我們熟知的託管語言有C#和Java,接下來,我們將以C#和Java為例介紹在託管環境中的編譯過程。
當我們在喜愛的IDE中編寫代碼時,第一個檢測我們代碼的就是IDE(詞法分析),然後,編譯成目標檔案和連結到動態/靜態庫或可執行檔進行再次檢查(文法分析),最後一次檢查是運行時檢查。託管環境中的一個共同特點是,編譯器不是產生二進位代碼,而是中間元代碼,稱為MSIL - Microsoft Intermediate Language在.NET中或位元組碼(Bytecode)在Java中。
在那之後,在運行時JIT(Just In Time)編譯器將MSIL翻譯成二進位代碼,這意味著我們的代碼在真正使用的時候才被解析,這允許在CLR(通用語言執行平台)先行編譯和最佳化我們的代碼,實現程式效能的提高,但增加了程式的啟動時間,我們也可以使用Ngen(Native Image Generator)先行編譯我們的程式,從而縮短程式的啟動時間,但沒有運行時最佳化的好處。
圖2 C#的編譯過程
.Net Framework就是在Win32 core上添加了一個抽象層,它提供的一個好處就是支援多語言、JIT最佳化、自動記憶體管理和改進安全性;另外一個完整解決方案是WinRT,但這涉及到另外一個主題了,這裡不作詳細介紹。
圖3 Windows API
JIT編譯的優點和缺點
JIT編譯帶來了許多好處,最大的一個在我看來是效能的優勢,它允許CLR(通用語言運行時扮演Assembler組件)只執行需要的代碼,例如:假設我們有一個非常大的WPF應用程式,它不是立即載入整個程式,而是CLR開始執行時,我們代碼的不同部分將通過一個高效的方法翻譯成本地指令,因為它能夠檢查系統JIT和產生最佳化的代碼,而不是按照一個預定義的模式。不幸的是,有一個缺點就是啟動的過程比較慢,這意味著它不適用於載入時間長的包。
JIT的替代方案使用NGen
如果Visual Studio由JIT建立,那麼它的啟動我們將需要等待幾分鐘,相反,如果它是使用Ngen(Native Image Generator)編譯,它將建立純二進位可執行檔,如果只考慮速度的問題,那是絕對是正確的選擇。
1.1.3總結
在非託管環境中,我們需要知道編譯的過程分成編譯和串連兩個階段,編譯階段將來源程式(*.c,*.cpp或*.h)轉換成為目標代碼(*.o或*.obj檔案),至於具體過程就是上面說的C/C++編譯過程的前三個階段;連結階段是把前面轉成成的目標代碼(obj檔案)與我們程式裡面調用的庫函數對應的代碼連結起來形成對應的可執行檔(exe檔案)。
託管環境中,編譯過程可以分為:詞法分析、文法分析、中間代碼產生、代碼最佳化和目標代碼產生等等過程;無論是.NET還是Java,它們都會產生中間代碼(MSIL或Bytecode),然後把最佳化後的中間代碼翻譯成目標代碼,最後在程式運行時,JIT將IL翻譯成機器碼。
無論是託管或非託管語言,它們的編譯編譯過程是把進階語言翻譯成電腦能理解的機器碼,由於編譯過程涉及的知識面很廣(編譯的原理和硬體知識),而且本人的能力有限,也只能簡單的描述一下這些過程,如果大家希望深入瞭解編譯的原理,我推薦大家看一下《編譯原理》。
參考
[1] http://www.developingthefuture.net/compilation-process-and-jit-compiler/