噢!我的編譯器 - Introduction I

前言

趁著這個寒假再趕緊複習近一年前選修過的 compiler,除了釐清整個架構流程與觀念,也期望能有對應的實做練習。其實只是下學期要當助教,得把這些東西撿回來 XD

之後的整理皆基於:

  • 龍書 (Compilers principles, techniques, and tools)
  • Stanford CS143 的開放式課程
  • 自己的想法

希望能夠闡述的更輕鬆且容易理解,大致上就這樣,我們開始吧!

Introduction I

其實編譯器的角色套用在現實生活中能夠特別清楚的解釋他的角色及功用 – 翻譯人員。不論是即時口譯還是各節目或動畫的專業字幕組都是,反正只要始能把 A 語言流暢的翻成 B 語言的都算。但翻譯的工作並不是那麼簡單,需要理解某語言的生字、語法才能夠進行,當然更專業的人員還能夠使用精簡的句子傳達意境,甚至即使他文法錯了,翻譯大大也能理解並精準的譯出正確的意思。總之,翻譯其實不僅僅是「翻譯」,還要再經過「編輯」,這也就是 “compile” 「編譯」的意思。

編譯器 Compiler

了解之後,我們再把視角拉回 compiler 上,compiler 就是程式語言間的翻譯員,不同的 compiler 會編譯成不同的語言,有可能是轉成機器語言(machine code)、byte code,甚至是另一種語言,如圖:

編譯器 compiler

產生出來的 target program 就能夠執行囉!所以程式的編譯到執行是這樣的:

從原始碼到編譯執行

直譯器 Interpreter

還有另一種語言處理的工具:直譯器 (interpreter)。相較於上圖,compiler 是編譯程式碼後產出可執行的程式碼,由使用者輸入 input 後,再得到 output。而直譯器是 source code 與 input 一次給,直接編譯並執行,產出 output ,而使用直譯器的語言有大名鼎鼎的 python。而的架構圖如下:

直譯器 Interpreter

而 compiler 與 interpreter 還有速度上的差異,compiler 產生的 target program 執行的比 interpreter 快。但 interpreter 的偵錯又比較好了,畢竟是一行行程式碼檢查與執行下來。

compilation + interpretation

再來,勢必要提及赫赫有名的 Java,為什麼呢?Java 是一個結合 compilation 和 interpretation 的程式語言,這是什麼意思?就是 Java 會先編譯成一種編碼稱為 byte code,接著再直譯成機器碼。這個的好處是,Java 經過一次編譯,就可以透過虛擬機 (virtual machine) 在不同的機器上直譯執行。沿用翻譯員的例子,byte code 就有像是目前的國際語言英文,只要 A 語言翻譯成英文,到 B 國人人都能直接把英語翻譯成自己的語言(當然前提是大家都會英文),因此到任何國家都能夠溝通了!整個架構可以繪製成下圖:

hybrid compiler

編譯系統 Compilation System

了解編譯器的角色與功能後,我們可以接著探討編譯系統是由哪些角色所組成的。

  1. 預處理 (preprocessor): 負責在引用 header file、libraries 的檔案插入完整的程式碼,以 C 為例就是根據 # 開頭的指令,e.g., #include stdio.h,直接插入 stdio.h 的內容。
  2. 編譯器 (compiler): 把重新編輯好的檔案再轉交給 compiler 編譯成組合語言 (assembly language),簡稱組語。而使用組語的最重要的原因是不同的高階程式語言都可以組譯成相同的組語,也比機器碼還好 debug。 p.s. 組語是因硬體架構而異。
  3. 組譯器 (assembler): 將組語轉譯為**機械碼 (machine code)**,並打包成重新定位的 **目標檔 (object file)**。
  4. 連結器 (linker): 負責合併所有 object files 並產生可執行的檔案,可以被加載到記憶體執行。

我們再把流程畫成下圖:

編譯系統

到目前為止,我們對編譯器以及編譯系統就有初步的了解了!