指令碼的執行方式,大緻有兩種:解釋和編譯。兩者都是以二進制目标機器碼為輸入,所采取的執行政策不同。
何為解釋?就是說将機器碼逐條讀出,每讀一條就進行解碼、執行。實作相對簡單,一般用進階語言編寫解釋器,移植性好。能夠實作精确控制,友善中斷、異常處理,且能實作目标硬體功能的完全模拟。缺點是效率低下。
編譯,就是把二進制機器碼按塊進行轉換,生成本地機器能夠直接運作的指令碼,并存放入緩沖區。它能夠實作代碼的高效運作,前提是緩沖區的代碼會被反複調用。
通常情況下解釋執行的速度慢于編譯執行。原因是解釋執行時,不管以前有沒有執行過,都要對目前的指令進行分析譯碼,而編譯執行能夠記住過去執行過代碼,當再次調用時直接從緩沖區中取出編譯好的代碼直接執行。舉個例子,比如一段循環代碼:sub這行它會執行100次,編譯執行時隻在第1次執行時運作編譯器,然後的99次均直接執行緩沖區中的本機代碼;解釋執行要有100次調用解釋器的開銷。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
mov r0, # 100
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
loop :
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
sub r0, r0, # 1
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
bne loop
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
一般編譯執行的流程如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
for (;;)
... {
pc=目前塊入口位址();
if(pc被緩沖)
...{
fp=擷取緩沖區入口位址(pc);
fp();// 執行緩沖區中的代碼
}
else
...{
生成代碼(pc);
}
}
編譯器編寫時要考慮的問題主要有:基本塊的劃分,中斷/異常模拟的實作,本機機器指令相關(如寄存器配置設定,指令編碼等)。
有張圖,展示了Mac上某x86模拟器動态編譯執行的架構: