前言
參考課上PPT内容。 該學習筆記目前僅打算個人使用。
後續會進一步整理,包括添加筆記内容,标明參考資料。
更新中。。。
跳過目錄
目錄
- 一、可移植性和抽象機
-
- 可移植和可适應
- 資訊流
- 基本模式
- 基本操作
- 抽象機
-
- 優點
- 抽象機代碼
- 二、Pascal 的 P-code 抽象機
- P-code 指令
- 補充:中間代碼生成執行個體——翻譯成字尾式
一、可移植性和抽象機
可移植和可适應
如果花較小的代價就能将一個程式遷移到另一台機器上,則稱該程式是可移植的(portable)
- 即遷移程式的開銷要顯著小于從頭開始編制程式的開銷。
如果一個程式能夠容易地進行修改就能滿足不同使用者和系統的需求,那麼稱該程式是可适應的(adaptable)。
假定要将一個給定的編譯程式從X機移植到Y機,則需要産生Y機的代碼,為此必須重寫現有編譯程式的代碼生成部分。
如果原來的編譯程式已分成前端和後端兩部分:
- 前端處理源語言
- 後端處理與目标機相關的部分
- 在前後端之間有一個良好的接口
那麼移植的主要工作僅僅是改變與目标機相關的部分。
資訊流
編譯程式兩部分之間的資訊流:
- 從前端到後端:為源語言上的基本操作
- 從後端到前端:為目标機的資訊。
兩者的接口能夠通過抽象機來實作,也即能夠将源語言的各種基本操作(fundamentaloperation)映射到該抽象機的僞操作上。
基本模式
- 可以是源語言中的類型(如Pascal中的整型和字元型),也可以是用來構造源語言中更複雜類型(如Pascal中構造類型)的模式。
基本操作
是指用于描述一個語言編寫的程式的最簡單、最直接的操作。
抽象機
可為特定的源語言設計抽象機,例如有為Pascal語言設計的抽象機。
抽象機模型是根據源語言(如Pascal)中基本的操作和模式來建立的。
編譯程式的前端将源程式翻譯成抽象機代碼,隻需要将源語言的各種結構分解為抽象機的基本模式下的基本操作序列。
由基本模式和基本操作所組成的對偶構成了抽象機上的一條指令。
抽象機的體系結構形成一個環境,在該環境中模式和操作互相作用來模拟源語言。
抽象機的設計者一方面要使抽象機能很容易地模拟源語言的各種結構所規定的操作,同時,還必須考慮能在實際計算機上高效地實作該抽象機的操作。
優點
-
使編譯程式的前端和後端清楚地分離。
将一個編譯程式移植到一台新的機器上,僅需要開發一個編譯程式的新的後端,對前端也隻需做少量的修改(必要時)。
例:在 n 台不同的機器上實作 m 種不同語言的編譯
- 若不使用某種中間代碼形式(如抽象機代碼),那麼必須要編寫 m × n 個不同的編譯程式。
- 若使用抽象機代碼,則僅需要m個前端和n個後端。使用這種方法,m × n 個不同的編譯程式能夠由 m + n 個部分組合而成。
如今,對一種程式設計語言,為幾種不同的目标機産生高效的目标代碼已是一件十分容易的事了。
一個較為困難的問題是要有一台抽象機,由該抽象機要能為幾種程式設計語言産生高效的目标代碼,同時,它又要能夠高效地模拟所有的程式設計語言。
因為各種程式設計語言(如FORTRAN、Lisp、Basic、Pascal和C)是有很大不同的,要找到這樣的抽象機幾乎不可能。
在計算機中,僞機器碼可被微程式設計為指令組由硬體執行。
抽象機代碼
許多Pascal編譯系統生成的中間代碼是一種稱為P-code的抽象代碼。
- P-code的“P”即“Pseudo”。
目前廣泛使用的Java語言,其編譯器生成的代碼實際上也是一種抽象機(即Java虛拟機)的代碼,稱為位元組碼(byte code)。
二、Pascal 的 P-code 抽象機
既然是“抽象機”,就是表示它并不是實際的實體目标機器而通常是虛拟的一台“堆棧計算機”。
該堆棧式計算機主要由若幹寄存器、一個儲存程式指令的儲存器(PC)和一個堆棧式資料及操作存儲組成。
棧:
- 用于存放所有可按源程式中的資料聲明進行直接尋址的資料
堆:
- 用于存放由程式員直接控制,即通過new語句所建立出來的資料
寄存器:
- PC:程式計數器,指向目前執行的指令。
- NP:堆指針,指向目前空閑堆空間的起始位置。
- SP:指針,指向目前棧頂位置。
- BP:基位址指針,即指向目前活動記錄的起始位置。
- MP:标志指針,指向目前活動記錄的基位址。
- EP:頂指針,指向目前程式子產品在棧中的最高位置。
棧式計算機的存儲情況如下:

問題:全局變量放在哪裡?
運作P-code的抽象機沒有專門的運算器或累加器,所有的運算(操作)都在運作棧的棧頂進行,如要進行運算
d := ( a + b ) * c
生成P– code序列為:
取a LOD a
取b LOD b
+ ADD
取c LOD c
* MUL
送d STO d
P-code 指令
P-code實際上是波蘭表示形式的中間代碼。
編譯程式生成P-code指令程式後,我們可以用一個解釋執行程式( interpreter)來解釋執行P-code ,當然也可以把P-code再變成某一機器的目标代碼。
顯然,生成抽象機P-code的編譯程式是很容易移植的。
補充:中間代碼生成執行個體——翻譯成字尾式
概念:拉鍊回填
begin
k := 100;
L: if k > i + j then
begin
k := k – 1;
goto L;
end
else k := i ^ 2 - j ^ 2;
i:= 0;
end
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | … |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- k := 100;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 k 100 := - k > i + j
1 2 3 4
L标号
5 6 7 8 9 10 11 12 13 14 15 16 k 100 := k i j + > - if then
1 2 3 4
L标号
5 6 7 8 9
label1
10 11 12 13 14 15 16 k 100 := k i j + > ? jez - 無法确定的位址先填入0。
- 一旦位址确定“回填”之!
1 2 3 4
L标号
5 6 7 8 9
label1
10 11 12 13 14 15 16 k 100 := k i j + > jez - k := k – 1;
1 2 3 4
L标号
5 6 7 8 9
label1
10 11 12 13 14 15 16 k 100 := k i j + > jez k k 1 - := - goto L;
1 2 3 4
L标号
5 6 7 8 9
label1
10 11 12 13 14 15 16 k 100 := k i j + > jez k k 1 - := 4 17 j - else
1 2 3 4
L标号
5 6 7 8 9
label1
10 11 12 13 14 15 16 k 100 := k i j + > jez k k 1 - := 4 17 18
label2
19 20 21 22 23 24 25 26 27 28 29 30 31 32 j ? j - k := i ^ 2 - j ^ 2;
1 2 3 4
L标号
5 6 7 8 9 10 11 12 13 14 15 16 k 100 := k i j + > 20 jez k k 1 - := 4 17 18
label2
19 20
label1
21 22 23 24 25 26 27 28 29 30 31 32 j j k i 2 ^ j 2 ^ - := - i := 0;
1 2 3 4
L标号
5 6 7 8 9
label1
10 11 12 13 14 15 16 k 100 := k i j + > 20 jez k k 1 - := 4 17 18
label2
19 20
label1
21 22 23 24 25 26 27 28 29
label2
30 31 32 j 29 j k i 2 ^ j 2 ^ - := i := …
注:
- 該中間代碼程式有死代碼,即永遠執行不到的代碼(18、19)