『壹』 一個軟體從源代碼到可執行程序,需要經歷幾個步驟的
一般經過編譯程序編譯後就可以直接執行了。
編譯程序一般有兩種執行方式:一種是邊解釋邊執行,一次將一條指令通過編譯程序編譯成機器代碼後執行,然後再編譯下一條指令,此種方式必須通過編譯程序來協助完成;另外一種是通過編譯程序直接將程序源代碼直接編輯成可執行文件,可執行文件可獨立執行,用不著編譯程序了。
『貳』 什麼是編譯原理
問題一:什麼是編譯原理 編譯:就是將程序語言進行翻譯,生成可供用戶直接執行的二進制代碼,即可執行文件。
任務是個比較模糊的概念,指的是操作系統中正在進行的工作,既可以指進程,也可以指程序春坦灶。
程序指的是可以連續執行,並能夠完成一定任務的一條條指令的 *** 。
進程是程序在一個數據 *** 上運行的過程,它是傳統操作系統進行資源分配和調度的一個獨立單位。
線程是一個指令執行序列,是操作系統調度的最小單位。一個或多個線程構成進程,構成一個進激的線程之間共享資源。進程和線程之間的最大區別就是線程不能獨立擁有資源,進程擁有自己的資源。
問題二:編譯原理中V*是什麼意思 V是一個符號 *** ,假設V指的是三個符號a, b, c的 *** ,記為 V = {a, b, c }
V* 讀作「V的閉包」,它的數學定義是V自身的任意多次自身連接(乘法)運算的積,也是一個 *** 。
也就是說,用V中的任意符號進行意多次(包括0次)連接,得到的符號串,都是V*這個 *** 中的元素。
0次連接的結果是不含任何符號的空串,記為 ε
1次連接就是只有一個符號的符號串,比如,a,b, c
2次連接是兩個符號構成的符號串,比如,aa, ab, ac, ba, bb, bc,等等
……
n次連接是一個長度為n、由a、b、c三個符號構成的符號串,比如abaacbbac……
因此,V*包含一切由a,b,c三個符號連接而成的、任意長度的符號串(以及空串ε)
問題三:編譯原理 V+什麼意思,例如下面的例子。。。 v表示終結符和非終結符 *** 。
+表示 *** 中的一個或多個元素構成的串的 *** 。
所以v+表示由一個或多個終結符或非終結符構成的串的 *** 。比如如果a∈VT,A∈VN,那麼a,A,aA,Aa,aAA,AaA等都是v+中的元素。
問題四:誰能夠解釋下編譯原理中什麼是FIRSTVT,和LASTVT,盡量淺顯易懂點謝謝 Firstvt和Lastvt是為了畫算符優先關系表的(就是表裡面填優先大於小於等於的那個)。
然後要注意他們可都是終結符的 *** 。
Firstvt
找Firstvt的三條規則:如果要找A的Firstvt,A的候選式中出現:
A->a.......,即以終結符開頭,該終結符入Firstvt
A->B.......,即以非終結符開頭,該非終結符的Firstvt入A的Firstvt
攻 A->Ba.....,即先以非終結符開頭,緊跟終結符,則終結符入Firstvt
Lastvt
找Lastvt的三條規則:如果要找A的Lastvt,A的候選式中出現:
A->.......a,即以終結符結尾,該終結符入Lastvt
A->.......B,即以非終結符結尾,該非終結符的Lastvt入A的Lastvt
A->.....aB,即先以非終結符結尾,前面是終結符,則終結符入Firstvt
問題五:編譯原理 什麼是語義分析 在編譯原理中,語法規則和詞法規則不同之處在於:規則主要識別單詞,而語法主要識別多個單片語成的句子。詞法分析信孝和詞法分析程序:詞法分析階段是編譯過程的第一個階段。這個階段的任務是從左到右一個字元一個字元地讀入源程序,即對構成源程序的字元流進行掃描然後根據構詞規則識別單詞(也稱單詞符號或符號)。詞法分析程序實現這個任務。詞法分析程序可以使用lex等工具自動生成。語法分析(Syntax *** ysis或Parsing)和語法分析程序(Parser) 語法分析是編譯過程的一個邏輯階段。語法分析的任務是在詞法分析的基礎上將單詞序列組合成各類語法短語,如「程序」,「語句」,「表達式」等等.語法分扒扮析程序判斷源程序在結構上是否正確.源程序的結構由上下文無關文法描述.語義分析(Syntax *** ysis) 語義分析是編譯過程的一個邏輯階段. 語義分析的任務是對結構上正確的源程序進行上下文有關性質的審查, 進行類型審查.語義分析將審查類型並報告錯誤:不能在表達式中使用一個數組變數,賦值語句的右端和左端的類型不匹配.
問題六:編譯原理中,(E)是什麼意思? E→(E)? 10分 就是 字元本身 意思是F產生( E ) 或者 i 比如If語句的開頭 就是 帶括弧的 必須是 if(表達式)這樣的形式 丟了任何即括弧就是其 終結符 「(」 和 「)」.
問題七:大家覺得對編譯器及編譯原理需要掌握到一個什麼程度 我跟你說,編譯原理太有用了。
我是做手機游戲的,現在做一個游戲引擎。既然是引擎,就需要提供抽象的東西給上層使用。這里,我引入了腳本系統。
這個腳本系統包括一堆我根據實際需求自行設計的指令集,包括基本的輸入輸出,四則運算,系統功能調用,函數聲明,調用等等(其實你要是用過lua或者其他游戲腳本你就知道了。)整個結構包括指令集、編譯器、虛擬機等部分。這樣,引擎提供一些基礎服務,比如繪圖,計算位置等,腳本就可以非常簡單控制游戲。甚至快速構建新游戲。你應該知道QUAKE引擎吧?
這里提供給你一個計算器的小程序,應用了EBNF理論,支持表達式,比如(2+3*6)*4+4,你自己體驗一下它的簡潔和強大。
/*
simple integer arithmetic calculator according to the EBNF
-> {}
->+|-
->{}
-> *
-> ( )| Number
Input a line of text from stdin
Outputs Error or the result.
*/
#include
#include
#include
char token;/*global token variable*/
/*function prototypes for recursive calls*/
int exp(void);
int term(void);
int factor(void);
void error(void)
{
fprintf(stderr,Error\n);
exit(1);
}
void match(char expectedToken)
{
if(token==expectedToken)token=getchar();
else error();
}
main()
{
int result;
token = getchar();/*load token with first character for lookahead*/
result = exp();
if(token=='\n')/*check for end of line */
printf(Result = %d\n,result);
else error();/*extraneous cahrs on line*/
return 0;
}
int exp(void)
{
int temp = term();
while((token=='+')||(token=='-'))
switch(token)
{
case '+':
match('+');
temp+=term......>>
問題八:編譯原理中,自動機究竟是什麼. 形式語言
形式語言 是一個字母表上的某些有限長字串的 *** 。一個形式語言可以包含無限多個字串。
語言的形式定義
字母表 ∑ 為任意有限 *** ,ε 表示空串, 記 ∑ 0 為{ε},全體長度為 n 的字串為 ∑ n , ∑ * 為 ∑ 0 ∪∑ 1 ∪…∪∑ n ∪…, 語言 L 定義為 ∑ * 的任意子集。
注記:∑ * 的空子集 Φ 與 {ε} 是兩個不同的語言。
語言間的運算
語言間的運算就是 ∑ * 冪集上的運算。
字串 *** 的交並補等運算。
連接運算:L 1 L 2 = { xy | x 屬於L 1 並且 y 屬於L 2 }。
冪運算:L n = L … L (共 n 個 L 連接在一起),L 0 = {ε}。
閉包運算:L * = L 0 ∪L 1 ∪…∪L n ∪…。
(右)商運算:L 1 /L 2 = {x | 存在 y 屬於L 2 使得 xy 屬於L 1 }。
語言的表示方法
一個形式語言可以通過多種方法來限定自身,比如:
枚舉出各個字串(只適用於有限字串 *** )。
通過 形式文法 來產生(參見 喬姆斯基譜系 )。
通過正則表達式來產生。
通過某種自動機來識別,比如 圖靈機 、 有限狀態自動機 。
自動機
automata
對信號序列進行邏輯處理的裝置。在自動控制領域內,是指離散數字系統的動態數學模型,可定義為一種邏輯結構,一種演算法或一種符號串變換。自動機這一術語也廣泛出現在許多其他相關的學科中,分別有不同的內容和研究目標。在計算機科學中自動機用作計算機和計算過程的動態數學模型,用來研究計算機的體系結構、邏輯操作、程序設計乃至計算復雜性理論。在語言學中則把自動機作為語言識別器,用來研究各種形式語言。在神經生理學中把自動機定義為神經網路的動態模型,用來研究神經生理活動和思維規律,探索人腦的機制。在生物學中有人把自動機作為生命體的生長發育模型,研究新陳代謝和遺傳變異。在數學中則用自動機定義可計算函數,研究各種演算法。現代自動機的一個重要特點是能與外界交換信息,並根據交換得來的信息改變自己的動作,即改變自己的功能,甚至改變自己的結構,以適應外界的變化。也就是說在一定程度上具有類似於生命有機體那樣的適應環境變化的能力。
自動機與一般機器的重要區別在於自動機具有固定的內在狀態,即具有記憶能力和識別判斷能力或決策能力,這正是現代信息處理系統的共同特點。因此,自動機適宜於作為信息處理系統乃至一切信息系統的數學模型。自動機可按其變數集和函數的特性分類,也可按其抽象結構和聯結方式分類。主要有:有限自動機和無限自動機、線性自動機和非線性自動機、確定型自動機和不確定型自動機、同步自動機和非同步自動機、級聯自動機和細胞自動機等。
這可能有你想要的答案
./question/7218281?fr=qrl3
問題九:編譯原理中"(E)"表示什麼 字元( 表達式 字元)
『叄』 計算機操作系統知識點
計算機操作系統知識點
網路的神奇作用吸引著越來越多的用戶加入其中,正因如此,網路的承受能力也面臨著越來越嚴峻的考驗―從硬體上、軟體上、所用標准上......,各項技術都需要適時應勢,對應發展,這正是網路迅速走向進步的催化劑。下面是關於計算機操作系統知識點,希望大家認真閱讀!
4.1.1操作系統的概念
操作系統:是管理計算機軟硬體資源的程序,同時它又是用戶與計算機硬體的介面。
4.1.2操作系統的構成
進程管理、內存管理、文件管理、輸入/輸出系統管理、二級存儲管理、聯網、保護系統、命令解釋程序
4.2.1操作系統的類別
經過多年的發展,操作系統多種多樣。為提高大型計算機系統的資源利用率,操作系統從批處理,多道程序發展為分時操作系統。為了滿足計算機處理實時事件的需要,就有實時操作系統。為適應個人計算機系統的需要又出現了桌面操作系統。為適應並行系統的需要,就有了多處理器操作系統。為滿足網路和分布計算的需要,就有了網路操作系統和分布式操作系統。此外,還有為支持嵌入式計算機的嵌入式操作系統。
4.2.2計算環境
從計算機誕生至今,操作系統總是與具體的計算環境相聯系,它總是在某種計算環境中設置和使用,就目前來看計算環境可分為以下幾類:
1.傳統計算環境
指普通意義下的獨立或聯網工作的通用計算機所形成的計算環境。
2.基於Web的計算環境
互聯網的普及使得計算被延伸到Web環境。
3.嵌入式計算環境
嵌入式計算機就是安裝在某些設備上的計算部件,其計算相對比較簡單。
4.3.1進程的概念
什麼是進程?它與程序有什麼區別?
程序:用戶為完成某一個特定問題而編寫的操作步驟。
進程:可以簡單地被看作是正在執行的程序。但是進程需要一定的資源來完成它的任務(例如CPU時間、內存、文件和I/O設備)。
進程與程序的區別在於進程是動態的、有生命力的,而程序是靜態的。一個程序載入到內存,系統就創建一個進程,程序執行結束後,該進程也就消亡了。
在計算機中,由於多個程序共享系統資源,就必然引發對CPU的爭奪。如何有效地利用CPU資源,如何在多個請求CPU的進程中選擇取捨,這就是進程管理要解決的問題。
4.3.3進程式控制制塊PCB(略)
為了控制進程,操作系統就必須知道進程存儲在哪裡,以及進程的一些屬性。
進程式控制制塊是進程實體的一部分,是操作系統中記錄進程的專用數據結構。一個新的進程創建時,操作系統就會為該進程建立一個進程式控制制塊。操作系統根據進程式控制制塊對並發進程進行控制。
4.3.4進程調度及隊列圖
計算機採用多道程序的目的是使得計算機系統無論何時都有進程運行,單處理器的計算機在某一時刻CPU只能運行一個進程,如果存在多個進程,其它進程就需要等待CPU空閑時才能被調度執行。
當一個進程處於等待或CPU時間片用完時,操作系統就會從該進程中拿走CPU控制權,然後再交給其它進程使用,這就是進程的調度。
4.3.5CPU調度及其准則
在設計CPU調度程序時主要應該考慮的准則包括:
(1)CPU使用率。讓CPU盡可能地忙。
(2)吞吐量。讓CPU在一定時間內完成的進程數盡可能多。
(3)周轉時間。讓進程從提交到運行完成的時間盡可能短。
(4)等待時間。讓進程在就緒隊列中等待所花時間之和盡可能短。
(5)響應時間。讓進程從提交請求到產生第一響應之間的時間盡可能短。
主要的CPU調度演算法
1、先到先服務
2、最短作業優先
3、優先權
4、輪轉
5、多級隊列
6、多級反饋隊列
4.3.7進程的同步與互斥
進程的同步就是指相互協作的進程不斷調整它們之間的相對速度,以實現共同有序地推進。
換句話說,在操作系統中,允許多個進程並發運行。然而,有些進程之間本身存在某種聯系,它們在系統中需要一種協作,以保證進程能正確有序地執行並維護數據的一致性。
在操作系統中,可能存在著多個進程。而系統中一些資源一次只允許一個進程使用,這類資源被稱為臨界資源。在進程中訪問臨界資源的那段程序稱為臨界區。當一個進程進入臨界區執行時,其它進程就不允許進入臨界區執行,否則就會導致錯誤結果。由此得出:
多個進程並發執行時,只允許一個進程進入臨界區運行,這就是進程的互斥。
例如:多個進程在競爭使用列印機時表現為互斥。
一個文件可供多個進程共享,其中有一個進程在寫操作時,其它進程則不允許同時寫或讀,表現為互斥。
4.3.8進程的死鎖及處理方法
在多道程序設計中,多個進程可能競爭一定數量的資源。一個進程在申請資源時,如果所申請資源不足,該進程就必須處於等待狀態。如果所申請的資源被其它進程佔有,那麼進程的等待狀態就可能無法改變,從而形成進程之間相互一直等待的局面,這就是死鎖。
競爭資源引起死鎖
引起死鎖的四個必要條件:
互斥:任一時刻只能有一個進程獨占某一資源,若另一進程申請該資源則需延遲到該資源釋放為止。
佔有並等待:即該進程佔有部分資源後還在等待其它資源,而該資源被其它進程佔有。
非搶占:某進程已佔用資源且不主動放棄它所佔有的資源時,其它進程不能強占該資源,只有等其完成任務並釋放資源。
循環等待:在出現死鎖的系統中,一定存在這樣一個進程鏈,其中每個進程至少佔有其它進程所必需的資源,從而形成一個等待鏈。
處理死鎖問題的三種方式:
可使用協議預防和避免死鎖,確保系統從不會進入死鎖狀態。
可允許系統進入死鎖狀態,然後檢測出死鎖狀態,並加以恢復。
可忽略進程死鎖問題,並假裝系統中死鎖從來不會發生。即沒有必要把精力花在小概率事件上。
處理死鎖優先考慮的順序:先預防和避免再檢測和恢復
4.4內存管理
內存是現代操作系統的核心。內存用於容納操作系統和各種用戶進程,是可以被CPU和I/O設備所共同訪問的數據倉庫。計算機的所有程序運行時都要調入內存。
內存管理的主要工作是:為每個用戶進程合理地分配內存,以保證各個進程之間在存儲區不發生沖突;當內存不足時,如何把內存和外存結合起來,給用戶提供一個比實際內存大得多的虛擬內存,使得程序能順利執行。內存管理包括內存分配、地址映射、內存保護和擴充。
4.4.1用戶程序執行與地址映射
用戶編寫程序在執行前,需要多個處理步驟,這些步驟可將源程序轉變為二進制機器代碼,然後在內存中等待執行。當然有時並非每個步驟都是必需的。
通常,將指令和數據的.地址映射成內存地址可以發生在以下三個執行階段。(了解)
1.編譯階段:如果在編譯時就知道進程將在內存中的什麼位置駐留,那麼編譯器就可以直接以生成絕對地址代碼。
2.載入階段:不知道進程將駐留在什麼位置,那麼編譯器就必須生成程序的邏輯地址,在載入階段再轉變成內存的絕對地址。
3.執行階段:如果進程在執行時可以從一個內存段移動到另一個內存段,那麼進程的絕對地址映射工作只能延遲到執行時進行。
4.4.2物理地址空間與邏輯地址空間
物理地址:是計算機內存單元的真實地址。
物理地址空間:由物理地址所構成的地址范圍。
邏輯地址:用戶程序地址,從0開始編址。
邏輯地址空間:由邏輯地址所構成的地址范圍。
地址映射:用戶程序在運行時要裝入內存,這就需要將邏輯地址變換成物理地址,這個過程稱為地址映射,也稱重定位。
用戶編寫的源程序是不考慮地址的,源程序經CPU編譯後產生邏輯地址。從CPU產生的邏輯地址轉換為內存中的物理地址的映射是由計算機中被稱為內存管理單元的硬體設備來實現的,將邏輯地址與內存管理單元中存放的內存基址相加就得到了物理地址。
4.4.3進程使用內存的交換技術
為了更加有效地使用內存,進程在不運行時,可以暫時從內存移至外存上,直到需要再運行時再重新調回到內存中。也就是說內存管理程序可將剛剛運行過的進程從內存中換出以釋放出佔用的內存空間,然後將另一個要運行的進程占據前者釋放的內存空間。
計算機工作時,為了將多個進程放入到內存就必須考慮在內存中如何放置這些進程。
4.4.4內存分配方案-連續
對於連續內存分配方案,開始時所有內存是一個大的孔,隨著內存分配的進行就會形成位置上不連續的大小不一的孔。在連續內存分配方案中,當新進程需要內存時,為其尋找合適的孔,實現內存分配。該方案為每個進程所分配的內存物理地址空間在位置上是連續的。
4.4.5內存分配方案-分頁式
分頁管理基本思想:
o內存物理地址空間劃分為若干個大小相等的塊(頁框)
o進程的邏輯地址空間也劃分為同樣大小的塊(頁面)
o內存分配時每個頁面對應地分配一個頁框,而一個進程所分得頁框在位置上不必是連續的。
頁表:操作系統為每個用戶程序建立一張頁表,該表記錄用戶程序的每個邏輯頁面存放在哪一個內存物理頁框。
4.5虛擬內存方案
虛擬內存是一個容量很大的存儲器的邏輯模型,它不是任何實際的物理存儲器,它一般是藉助硬碟來擴大主存的容量。
虛擬內存:對於一個進程來講,如果僅將當前要運行的幾個頁面裝入內存便可以開始運行,而其餘頁面可暫時留在磁碟上,待需要時再調入內存,並且調入時也不佔用新的內存空間,而是對原來運行過的頁面進行置換。這樣,就可以在計算機有限的內存中同時駐留多個進程並運行。而對用戶來講感覺到系統提供了足夠大的物理內存,而實際上並非真實的,這就是虛擬內存。
4.5.2頁面請求與頁面置換演算法
頁面請求:在虛擬內存技術中,進程運行時並沒有將所有頁面裝入到內存,在運行過程中進程會不斷地請求頁面,如果訪問的頁面已在內存,就繼續執行下去;但如果要訪問的頁面尚未調入到內存,便請求操作系統將所缺頁面調入內存,以便進程能繼續運行下去。
頁面置換:如果請求頁面調入內存時,分配給該進程的頁框已用完,就無法立即裝入所請求頁面。此時,必須將進程中的某個頁面從內存的頁框調出到磁碟上,再從磁碟上將所請求的頁面調入到內存的該頁框中。這個過程叫做頁面置換。
4.6文件管理
文件管理是操作系統最常見的組成部分。文件管理主要提供目錄及其文件的管理。
4.6.1文件的概念
文件:保存在外部存儲設備上的相關信息的集合。
文件命名:文件主名+擴展名
文件存取屬性:
只讀:只允許授權用戶進行讀操作。
讀寫:只允許授權用戶進行讀和寫的操作。
文檔:允許任何用戶進行讀寫操作。
隱藏:不允許用戶直接看到文件名。
文件系統:是對文件進行操作和管理的軟體,是用戶與外存之間的介面。這個系統將所有文件組織成目錄結構保存在外存,一個文件對應其中的一個目錄條。目錄條記錄有文件名、文件位置等信息。
操作系統對文件的基本操作包括:
創建文件、文件寫、文件讀、文件重定位、文件刪除、文件截短。
對文件的其它操作包括:文件復制、重命名、更改屬性等。
;『肆』 編譯詳細資料大全
編譯(compilation , compile) 1、利用編譯程式從源語言編寫的源程式產生目標程式的過程。 2、用編譯程式產生目標程式的動作。 編譯就是把高級語言變成計算機可以識別的2進制語言,計算機只認識1和0,編譯程式把人們熟悉兆猜吵的語言換成2進制的。 編譯程式把一個兆晌源程式翻譯成目標程式的工作過程分為五個階段:詞法分析;語法分析;語義檢查和中間代碼生成;代碼最佳化;目標代碼生成。主要是進行詞法分析和語法分析,又稱為源程式分析,分析過程中發現有語法錯誤,給出提示信息。
編譯語言是一種以編譯器來實現的程式語言。它不像直譯語言一樣,由解釋器將代碼一句一句運行,而是以編譯器,先將代碼編譯為機器碼,再加以運行。理論上,任何程式語言都可以是編譯式,或直譯式的。它們之間的區別,僅與程式的套用有關。
『伍』 程序在 編譯期,鏈接期,運行期各執行哪些操作
參考一下:
源文件的編譯過程包含兩個主要階段,而它們之間的轉換是自動的。第一個階段是預處理階段,在正式的編譯階段之前進行。預處理階段將根據已放置在文件中的預處理指令來修改源文件的內容。#include指令就是一個預處理指令,它把頭文件的內容添加到.cpp文件中還有其他許多預處理指令
這個在編譯之前修改源文件的方式提供了很大的靈活性,以適應不同的計算機和操作系統環境的限制。一個環境需要的代碼跟另一個環境所需的代碼可能有所不同,因為可用的硬體或操作系統是不同的。在許多情況下,可以把用於不同環境的代碼放在同一個文件中,再在預處理階段修改代碼,使之適應當前的環境。
預處理器顯示為一個獨立的操作,但一般不能獨立於編譯器來執行這個操作。調用編譯器會自動執行預處理過程,之後才編譯代碼。
編譯器為給定源文件輸出的是機器碼,執行這個過程需要較長時間。在對象文件之間並沒有建立任何連接。對應於某個源文件的對象文件包含在其他源文件中定義的函數引用或其他指定項的引用,而這些函數或項仍沒有被解析。同樣,也沒有建立同庫函數的鏈接。實際上,這些函數的代碼並不是文件的一部分。這些工作是由鏈接程序(有時稱為鏈接編輯器)完成的
鏈接程序把所有對象文件中的機器碼組合在一起,並解析它們之間的交叉引用。它還集成了對象模塊所使用的庫函數的代碼。這是鏈接程序的一種簡化表示,因為這里假定在可執行模塊中,模塊之間的所有鏈接都是靜態建立的。實際上有些鏈接是動態的,即這些鏈接是在程序執行時建立的。
鏈接程序靜態地建立函數之間的鏈接,即在程序執行之前建立組成程序的源文件中所包含的函數鏈接。動態建立的函數之間的鏈接(在程序執行過程中建立的鏈接)將函數編譯並鏈接起來,創建另一種可執行模塊—— 動態鏈接庫或共享庫。動態鏈接庫中的函數鏈接是在程序調用函數時才建立的,在程序調用之前,該鏈接是不存在的。
動態鏈接庫有幾個重要的優點。一個主要的優點是動態鏈接庫中的函數可以在幾個並行執行的程序之間共享,這將節省相同函數佔用的內存空間。另一個優點是動態鏈接庫在調用其中的函數之前是不會載入到內存中的。也就是說,如果不使用給定動態鏈接庫中的函數,該動態鏈接庫就不會佔用內存空間
『陸』 編譯原理的相關程序
解釋程序(interpreter):解釋程序是如同編譯器的一種語言翻譯程序。它與編譯器的不同之處在於:它立即執行源程序而不是生成在翻譯完成之後才執行的目標代碼。從原理上講,任何程序設計語言都可被解釋或被編譯,但是根據所使用的語言和翻譯情況,很可能會選用解釋程序而不用編譯器。例如, 我們經常解釋BASIC語言而不是去編譯它。類似地,諸如LISP 的函數語言也常常是被解釋的。
解釋程序也經常用於教育和軟體的開發,此處的程序很有可能被翻譯若干次。而另一方面,當執行的速度是最為重要的因素時就使用編譯器,這是因為被編譯的目標代碼比被解釋的源代碼要快得多,有時要快10倍或更多。但是,解釋程序具有許多與編譯器共享的操作,而兩者之間也有一些混合之處。 代碼生成(code generator):代碼生成器得到中間代碼(IR),並生成目標機器的代碼。正是在編譯的這個階段中,目標機器的特性成為了主要因素。當它存在於目標機器時,使用指令不僅是必須的而且數據的形式表示也起著重要的作用。例如,整型數據類型的變數和浮點數據類型的變數在存儲器中所佔的位元組數或字數也很重要。在上面的示例中,現在必須決定怎樣存儲整型數來為數組索引生成代碼。例如,下面是所給表達式的一個可能的樣本代碼序列(在假設的匯編語言中):
M O V R0,index ;;
value of index -> R0 M U L R0,2 ;;
double value in R0 M O V R1,&a ;;
address of a -> R1 A D D R1,R0 ;;
add R0 to R1 M O V *R1,6 ;;
constant 6 -> address in R1
在以上代碼中,為編址模式使用了一個類似C的協定,因此& a是a的地址(也就是數組的基地址),* R1則意味著間接寄存器地址(因此最後一條指令將值6存放在R1包含的地址中)。這個代碼還假設機器執行位元組編址,並且整型數占據存儲器的兩個位元組(所以在第2條指令中用2作為乘數)。 目標代碼(target code optimizer ):在這個階段中,編譯器嘗試著改進由代碼生成器生成的目標代碼。這種改進包括選擇編址模式以提高性能、將速度慢的指令更換成速度快的,以及刪除多餘的操作。在上面給出的樣本目標代碼中,還可以做許多更改:在第2條指令中,利用移位指令替代乘法(通常地,乘法很費時間),還可以使用更有效的編址模式(例如用索引地址來執行數組 存儲)。使用了這兩種優化後,目標代碼就變成:
MOV R0,index ;;
value of index -> R0 SHL R0 ;;
double value in R0 MOV &a[R0],6 ;;
constant 6 -> address a + R0
到這里就是編譯原理的簡要描述,但還應特別強調編譯器在其結構細節上差別很大。