preface前 言
本書適合誰讀
本書是一本描述編譯系統實現的書籍。這裡使用「編譯系統」一詞,主要是為了與市面上描述編譯器實現的書籍進行區分。本書描述的編譯系統不僅包含編譯器的實現,還包括彙編器、鏈結器的實現,以及機器指令與可執行檔案格式的知識。因此,本書使用「編譯系統」一詞作為編譯器、彙編器和鏈結器的統稱。
本書的目的是希望讀者能通過閱讀本書清晰地認識編譯系統的工作流程,並能自己嘗試構造乙個完整的編譯系統。為了使讀者更容易理解和學習編譯系統的構造方法,本書將描述的重點放在編譯系統的關鍵流程上,並對工業化編譯系統的實現做了適當的簡化。如果讀者對編譯系統實現的內幕感興趣,或者想自己動手實現乙個編譯系統的話,本書將非常適合你閱讀。
閱讀本書,你會發現書中的內容與傳統的編譯原理教材以及描述編譯器實現的書籍有所不同。本書除了描述乙個編譯器的具體實現外,還描述了一般書籍較少涉及的彙編器和鏈結器的具體實現。而且本書並非「紙上談兵」,在講述每個功能模組時,書中都會結合具體實現**來闡述模組功能的實現。通過本書讀者將會學習如何使用有限自動機構造詞法分析器,如何將文法分析演算法應用到語法分析過程,如何使用資料流分析進行中間**的優化,如何生成合法的彙編**,如何產生二進位制指令資訊,如何在鏈結器內進行符號解析和重定位,如何生成目標檔案和可執行檔案等。
本書的宗旨是為意欲了解或親自實現編譯系統的讀者提供指導和幫助。尤其是計算機專業的讀者,通過自己動手寫出乙個編譯系統,能加強讀者對計算機系統從軟體層次到硬體層次的理解。同時,深入挖掘技術幕後的秘密也是對專業興趣的一種良好培養。gcc本身是一套非常完善的工業化編譯系統(雖然我們習慣上稱它為編譯器),然而單憑個人之力無法做到像gcc這樣完善,而且很多時候是沒有必要做出乙個工程化的編譯器的。本書試圖幫助讀者深入理解編譯的過程,並能按照書中的指導實現乙個能正常工作的編譯器。在自己親自動手實現乙個編譯系統的過程中,讀者獲得的不僅僅是軟體開發的經歷。在開發編譯系統的過程中,讀者還會學習很多與底層相關的知識,而這些知識在一般的專業教材中很少涉及。
基礎知識儲備
本書盡可能地不要求讀者有太多的基礎知識準備,但是編譯理論屬於計算機學科比較深層次的知識領域,難免對讀者的知識儲備有所要求。本書的編譯系統是基於linux x86平台實現的,因此要求讀者對linux環境的c/c++程式設計有所了解。另外,理解彙編器的實現內容需要讀者對x86的彙編指令程式設計比較熟悉。本書不會描述過多編譯原理教材中涉及的內容,所以要求讀者具備編譯原理的基礎知識。不過讀者不必過於擔心,本書會按照循序漸進的方式描述編譯系統的實現,在具體的章節中會將編譯系統實現的每個細節以及所需的知識闡述清楚。
本書內容組織
本書共7章,各章的主要內容分別如下。
第1章**背後
從程式設計開始,追溯**背後的細節,引出編譯系統的概念。
第2章編譯系統設計
按照編譯系統的工作流程,介紹本書編譯系統的設計結構。
第3章編譯器構造
描述如何使用有限自動機識別自定義高階語言的詞法記號,如何使用文法分析演算法識別程式的語法模組,如何對高階語言上下文相關資訊進行語義合法性檢查,如何使用語法制導翻譯進行**生成,以及編譯器工作時符號資訊的管理等。
第4章編譯優化
介紹中間**的設計和生成,如何利用資料流分析實現中間**優化,如何對變數進行暫存器分配,目標**生成階段如何使用窺孔優化器對目標**進行優化。
第5章二進位制表示
描述intel x86指令的基本格式,並將at&t彙編與intel彙編進行對比。描述elf檔案的基本格式,介紹elf檔案的組織和操作方法。
第6章彙編器構造
描述彙編器詞法分析和語法分析的實現,介紹彙編器如何提取目標檔案的主要表資訊,並描述x86二進位制指令的輸出方法。
第7章鏈結器構造
隨書原始碼
本書實現的編譯系統**已經託管到github,原始碼可以使用gcc 5.2.0編譯通過。**的github位址是**分支x86實現了基於intel x86體系結構的編譯器、彙編器和鏈結器,編譯系統生成的目標檔案和可執行檔案都是linux下標準的elf檔案格式。**分支arm實現了基於arm體系結構的編譯器,目前支援生成arm 7的彙編**。
目 錄 contents 序
前言第1章 **背後
1.1 從程式設計聊起
1.2 歷史淵源
1.3 gcc的工作流程
1.3.1 預編譯
1.3.2 編譯
1.3.3 彙編
1.3.4 鏈結
第2章 編譯系統設計
2.1 編譯程式的設計
2.1.1 詞法分析
2.1.3 符號表管理
2.1.6 編譯優化
2.4 匯程式設計序的設計
2.4.1 彙編詞法、語法分析
2.4.2 表資訊生成
2.4.3 指令生成
2.5 鏈結程式的設計
2.5.1 位址空間分配
2.5.3 重定位
2.6 本章小結
第3章 編譯器構造
3.1 詞法分析
3.1.1 掃瞄器
3.1.2 詞法記號
3.1.3 有限自動機
3.1.4 解析器
3.1.5 錯誤處理
3.2 語法分析
3.2.1 文法定義
3.2.2 遞迴下降子程式
3.2.3 錯誤處理
3.3 符號表管理
3.3.1 符號表資料結構
3.3.2 作用域管理
3.3.3 變數管理
3.3.4 函式管理
3.4 語義分析
3.4.1 宣告與定義語義檢查
3.4.2 表示式語義檢查
3.4.3 語句語義檢查
3.4.4 錯誤處理
3.5 **生成
3.5.1 中間**設計
3.5.2 程式執行時儲存
3.5.3 函式定義與return語句翻譯
3.5.4 表示式翻譯
3.5.5 復合語句與break、continue
語句翻譯
3.5.6?目標**生成
3.5.7 資料段生成
3.6 本章小結
第4章 編譯優化
4.1 資料流分析
4.1.1 流圖
4.1.2 資料流分析框架
4.2 中間**優化
4.2.1 常量傳播
4.2.2 複寫傳播
4.2.3 死**消除
4.3 暫存器分配
4.3.1 圖著色演算法
4.3.2 變數棧幀偏移計算
4.4 窺孔優化
4.5 本章小結
第5章 二進位制表示
5.1 x86指令
5.1.1 指令字首
5.1.2 操作碼
5.1.3 modr/m欄位
5.1.4 sib欄位
5.1.5 偏移
5.1.6 立即數
5.1.7 at&t彙編格式
5.2 elf檔案
5.2.1 檔案頭
5.2.2 段表
5.2.3 程式頭表
5.2.4 符號表
5.2.5 重定位表
5.2.6 串表
5.3 本章小結
第6章 彙編器構造
6.1 詞法分析
6.1.1 詞法記號
6.1.2 有限自動機
6.2 語法分析
6.2.1 組合語言程式
6.2.2 資料定義
6.2.3 指令
6.3 符號表管理
6.3.1 資料結構
6.3.2 符號管理
6.4 表資訊生成
6.4.1 段表資訊
6.4.2 符號表資訊
6.4.3 重定位表資訊
6.5 指令生成
6.5.1?雙運算元指令
6.5.2?單運算元指令
6.5.3 零運算元指令
6.6 目標檔案生成
6.7 本章小結
第7章 鏈結器構造
7.1 資訊收集
7.1.1 目標檔案資訊
7.1.2 段資料資訊
7.1.3 符號引用資訊
7.2 位址空間分配
7.3 符號解析
7.3.1 符號引用驗證
7.3.2 符號位址解析
7.4 重定位
7.5 程式入口點與執行時庫
7.6 可執行檔案生成
7.7 本章小結
參考文獻
OpenWRT系統編譯
openwrt系統編譯完成之後在bin ramips目錄下存放系統映象,如下圖所示,其中openwrt ramips mt7688 root.squashfs檔案是根檔案系統 squashfs 是一套基於linux核心使用的壓縮唯讀檔案系統。該檔案系統能夠壓縮系統內的文件,inode 以及目錄,檔案...
WinCE系統編譯過程
在wince系統中,當我們完成了相關的開發和系統定製工作以後,會編譯wince系統,最後生成nk.bin和nk.nb0。我現在用wince6.0在自己的pc上面編譯一次用時19分16秒 有一天無聊,就測了一下 下面介紹一下wince系統的編譯過程,大致分為4個階段 編譯階段 compile phas...
Mac系統編譯FFmpeg
接下來介紹一下如何在mac系統上編譯ffmpeg。首先你需要安裝兩個工具 xcode homebrew。安裝xcode的原因是xcode提供了mac平台開發環境必須的gcc編譯器。這裡假設你一進安裝了xcode 和 homebrew。如果還沒有安裝,請先安裝,在繼續下面的操作 在終端執行命令 bre...