一文帶你快速瞭解編譯原理

什麼是程序的執行?

輸入
程序
輸出

程序可以看做一個函數,接受輸入和返回輸出?

什麼是編譯器?

源程序
編譯器
目標程序

將源程序編譯成 目標程序。
代表:

  • c/c++
  • go
  • rust

什麼是解釋器?

源程序
解釋器
輸入
輸出

代表:

  • python
  • lua

混合編譯器

源程序
第一次編譯
中間代碼
第二次編譯
虛擬機
輸入
輸出
  • 中間代碼更容易被翻譯成目標程序、優化空間更大
  • 中間語言的存在更利於編譯器的實現
  • 讓虛擬機處理複雜的執行環境(跨平臺)

代表:

  • java

即時編譯器(Just-in-time compiler)

  • 一種提高效率的方法,中間代碼不是直接執行,而是先被編譯成機器碼執行。
  • java

交叉編譯

  • 在一個平臺編譯產生多個平臺的可執行代碼
編譯平臺Mac
Linux_ARM
Windows_x64
Linux_x64

不同方式優劣勢

  • 解釋執行有性能問題,但也異常靈活,例如支持eval函數,eval 本質上 就是c語言的函數指針,將cs:ip 指向文本,這樣就能將一串文本 轉換成 代碼了。
  • 直接交叉編譯技術難度是其次,跨平臺問題會多;一次編譯很多包也有分發問題----產品問題。
  • 虛擬化技術提供更好的體驗,卻沒有 提供更好的性能(JIT完美解決這一點)。

編譯階段

詞法分析
語法分析
編譯平臺Mac
Windows_x64
Linux_x64

詞法分析(Parser):

將字符序列轉換爲單詞(Token)序列的過程, 分詞斷句 + 判斷詞性的過程。

給定:

var a = 5 * 6.0 + 7;

token 詞性
var 關鍵字
a 變量
= 運算符
5 整型
* 運算符
6.0 浮點型
+ 運算符
7 整形

語法分析(LEXical):

學過因爲的都知道,單詞不是隨便都能組合的,按照"主謂賓" i eat a apple 我們可以把一句話,生成一個ast抽象語法樹(Abstract Syntax Tree),用來輔助直接計算或者輔助編譯器生成字節碼的結構。
在這裏插入圖片描述

在這裏插入圖片描述

我們 對 這顆 AST樹進行後序(左、右、上) 輸出, 5、6.0 、* 、 7 、+ ,到了 這 我們 就可以很方便使用棧的數據結構模擬進行計算了。
在這裏插入圖片描述
語法 分析,可以從前往後 也可以從後往前,一般來說從前往後去解析語法比較方便,解析語法樹 我們可以通過 一個表達式,

expr -> number op expr|number

上面的表達式 比較抽象, 舉個例子

expr = 1 + 2 + 3 + 5 + 6

expr = 1 + expr1 = ↓
expr = 1 + 2 + expr2 =↓
expr = 1 + 2 + 3 + expr3 = ↓
expr = 1 + 2 + 3 + 5 + expr4

可以看到 expr3 = 5 + expr4 、此時 expr4 = 6 是一個number 那麼,遞歸節結束。
上面,的例子 expr表達式 就是將 一個問題 像套娃、分形圖 一樣拆解成 一個數 操作符 和 另一個更小規模的expr表達式 ,這就是遞歸的思維 表達式的最後一層套娃是一個number。

運行時環境

  • 有的編譯器將代碼編譯成機器碼,按照操作系統約定編譯成一個應用,運行稱爲操作系統的進程.
  • 有的編譯器將代碼編譯成中間代碼(字節碼、三地址代碼等),然後在操作系統中啓動一個虛擬容器(進程)來執行他們。
  • JIT編譯器一邊執行中間代碼,一邊編譯他們。

編譯器分層

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章