Download presentation
Presentation is loading. Please wait.
1
第 12 章、系統軟體實作 作者:陳鍾誠 旗標出版社
2
第 12 章、系統軟體實作 12.1 簡介 12.2 組譯器實作 12.3 虛擬機實作 12.4 剖析器實作 12.5 編譯器實作
簡介 組譯器實作 虛擬機實作 剖析器實作 編譯器實作 整合測試
3
12.1 簡介 C 語言實作 目的 動態陣列 + 雜湊表格 (12.1 節) 組譯器 (12.2 節) 虛擬機器 (12.3 節)
簡介 C 語言實作 動態陣列 + 雜湊表格 (12.1 節) 組譯器 (12.2 節) 虛擬機器 (12.3 節) 剖析器 (12.4 節) 編譯器 (12.5 節) 目的 展示系統軟體的實作方法與技巧 讓讀者熟悉系統軟體的原理 培養開發系統軟體的能力 以實作印證理論, 以理論支持實作
4
實作程式列表
5
動態陣列 實作目的 標準 C 語言函式庫當中缺乏一些基本資料結構的相 關函數, 因此我們必須先設計出這些資料結構, 像是 動態陣列 (Array)、雜湊表 (Hash Table) 等 以便在後續的組譯器、虛擬機、剖析器與編譯器中, 可以很容易的利用這些結構存放像符號表、指令表、 詞彙串列、剖析樹等資料。
6
動態陣列的資料結構與函數
7
動態陣列新增 – ArrayAdd()
8
動態陣列的使用
9
動態陣列的測試結果
10
動態陣列的列舉 - ArrayEach()
11
雜湊表 實作目的 標準 C 語言函式庫當中缺乏一些基本資料結構的相 關函數, 因此我們必須先設計出這些資料結構, 像是 動態陣列 (Array)、雜湊表 (Hash Table) 等 以便在後續的組譯器、虛擬機、剖析器與編譯器中, 可以很容易的利用這些結構存放像符號表、指令表、 詞彙串列、剖析樹等資料。
12
雜湊表的資料結構與函數
13
雜湊函數的實作 將字串 key 中的每個位元組相加後, 對雜湊表的大小取 餘數後的結果 這個方法雖然不是很好的雜湊函數,但是簡單卻足夠 了。
14
雜湊表:取得對應鍵值的元素 - HashTableGet(table, key)
15
雜湊表:放入鍵值與元素 - HashTablePut(table, key, data)
16
12.2 組譯器實作 撰寫一個簡單的 CPU0 組譯器 – as0 印證組譯器的理論 學習組譯器的實作方式 使用方式
組譯器實作 撰寫一個簡單的 CPU0 組譯器 – as0 印證組譯器的理論 學習組譯器的實作方式 使用方式 as0 <asmFile> <objFile>
17
組譯範例:as0 ArraySum.asm0 ArraySum.obj0
18
組譯器的資料結構
19
組譯器的函數
20
組譯器的主要函數 – assemble(asmFile, objFile)
21
組譯器的第一階段 (計算符號位址)
22
計算指令大小 – AsmCodeSize()
23
組譯器的第2階段
24
指令轉機器碼 (J 型指令)
25
指令轉機器碼 (A 型指令)
26
資料轉二進位碼
27
12.3 虛擬機實作 當我們用 as0 組譯出了目的碼之後, 這個目的碼仍 然無法被執行
虛擬機實作 當我們用 as0 組譯出了目的碼之後, 這個目的碼仍 然無法被執行 這是因為筆者所使用的處理器並不是 CPU0, 而是 Intel 的 IA32 CPU 為核心的電腦。 為了讓讀者能執行 CPU0 的目的碼, 筆者只好繼續 撰寫一個虛擬機器 vm0 以便讓讀者執行 as0 所組譯出的目的碼, 本節將描 述 vm0 的使用方式與設計原理。
28
虛擬機的執行 vm0 ArraySum.obj0
29
執行後的傾印
30
虛擬機的資料結構與函數
31
虛擬機的最上層函數 – runObjFile(objFile)
32
虛擬機使用的位元操作函數
33
定義暫存器別名
34
虛擬機的主要函數 – Cpu0Run()
35
Cpu0Run() - 指令擷取階段
36
Cpu0Run() – 解碼階段
37
Cpu0Run() – 執行階段 (載入指令)
38
Cpu0Run() – 執行階段 (運算指令)
39
Cpu0Run() – 執行階段 (跳躍指令)
40
Cpu0Run() – 執行階段 (結尾)
41
虛擬機:傾印暫存器 - Cpu0Dump()
42
12.4 剖析器實作 C0 語言的剖析器 (Parser) 是編譯器與直譯器中的關鍵程式 作為 c0c 編譯器的語法剖析程式
剖析器實作 C0 語言的剖析器 (Parser) 是編譯器與直譯器中的關鍵程式 作為 c0c 編譯器的語法剖析程式 會呼叫詞彙掃描器 Scanner 取的詞彙
43
掃描器 詞彙掃描器 Scanner 是一個較為簡單的物件 用來取得下一個詞彙 (token) 提供剖析器呼叫使用
44
掃描器的使用方法
45
掃描器的資料結構
46
判斷詞彙的型態 – tokenToType(token)
47
掃描器的主要函數
48
剖析器 Parser.h 剖析器的資料結構與函數宣告 Parser.c 剖析器的程式實作
49
剖析器的資料結構與函數
50
剖析器的最上層函數 parse()
51
遞迴下降剖析法
52
剖析 for 迴圈語法
53
剖析器中的 next() 函數
54
剖析器中的 push(), pop() 函數
55
圖 12.1 遞迴下降剖析器的執行過程 … PROG BaseList BASE STMT 成 長 方 向 堆疊 (Stack)
圖 遞迴下降剖析器的執行過程 PROG BaseList BASE STMT 成 長 方 向 堆疊 (Stack) i : id = 0:number EXP ITEM FOR ( for …
56
12.5 編譯器實作 c0c 編譯器 執行方法 輸入:C0 語法的程式 輸出:CPU0 的組合語言
編譯器實作 c0c 編譯器 輸入:C0 語法的程式 輸出:CPU0 的組合語言 執行方法 c0c <c0File> <asmFile>
57
編譯的範例
58
編譯器的最上層函數 範例 12.24 的 compile(cFile, asmFile) 剖析器:parse(cText)
程式產生器: generate(parser->tree, asmFile)
59
程式碼產生器的最上層函數
60
程式碼產生器的資料結構與函數
61
程式碼產生器 GenCode() – 開頭
62
GenCode() – 處理 FOR
63
GenCode() – 處理 STMT
64
GenCode() – 處理 COND
65
GenCode() – 處理 EXP
66
GenCode() – 結尾
67
輸出中間碼 P-Code
68
P-Code 轉為組合語言 (前半段)
69
P-Code 轉為組合語言 (後半段)
70
輸出組合語言
71
12.6 整合測試 單一主程式, 以條件編譯的方式 方法是利用 C 語言的巨集編譯指令
整合測試 單一主程式, 以條件編譯的方式 編譯出 test, c0c, as0, vm0 等四個執行檔 方法是利用 C 語言的巨集編譯指令 #if … #elif…#endif
72
整個系統的主程式 (前半段)
73
整個系統的主程式 (後半段)
74
專案建置檔 makefile (第1部分)
75
專案建置檔 makefile (第2部分)
76
專案建置檔 makefile (第3部分)
77
建置執行過程 (1)
78
執行:編譯器 (剖析)
79
執行:編譯器 (中間碼產生)
80
執行:編譯器 (產生組合語言)
81
執行:組譯器 (第1階段:計算符號位址)
82
執行:組譯器 (第2階段:指令轉機器碼)
83
執行:組譯器 (輸出:目的碼)
84
執行:虛擬機
85
結語 系統軟體實作 本章以 C 語言實作了 動態陣列 雜湊表 編譯器 c0c test.c0 test.asm0 組譯器
as0 test.asm0 test.obj0 虛擬機 vm0 test.obj0
86
習題 12.1 請撰寫一個 C0 語言的程式 fib.c0, 可以利用 for 迴圈的方式算出費氏序列 中的 f(10) 的值, 費氏序列的規則為 f(n) = f(n-1)+f(n-2), 而且 f(0) = 1, f(1)=1。 請利用 c0c 編譯器, 將 fib.c0 編譯為組合語言 fib.asm0。 請利用 as0 組譯器, 將 fib.asm0 組譯為目的檔 fib.obj0。 請利用 vm0 虛擬機, 執行 fib.obj0, 並檢查看看 f(10) 的結果是否正確。 請為 C0 語言加上 if 條件的規則為 IF = ‘if’ ‘(’ COND ‘)’ BLOCK (‘ elseif’ BLOCK)* (else BLOCK)?, 然後修改本章的剖析器程式, 加入可以處理該規則的 程式。 繼續前一題, 請修改本章的程式碼產生器程式, 以產生上述的 if 規則之程 式。
Similar presentations