在《d parser 之前:寫乙個簡單的虛擬機器》裡,其中計算 1 到 100 之和的程式 add.bin,是使用十六進製制編輯器直接編輯出來的。虛擬機器製作完後,考慮了一下,如果直接寫 z 的編譯器,難度還是不小,所以決定,先寫乙個組合語言的編譯器,實現從彙編**到機器**的編譯工作。
大體來說,彙編編譯基本上是一條一條對照生成,不過,行號的需求使得其中多了一些複雜性,另外,我還決定加入注釋的支援。所以,這也是乙個比較好的機會實踐一下分析器生成器的使用。
組合語言部分做了少量修改,over 改為 end,行號改為加 @ 字首,完成的 grammatica 的分析檔案如下:
%header%
grammartype = "ll"
description = "a asm grammar for zvm."
author = "lephone liang"
version = "1.0"
date = "7 january 2008"
license = "."
%tokens%
eax = "eax"
ebx = "ebx"
esp = "esp"
eip = "eip"
set = "set"
mov = "mov"
tjmp = "jmp"
add = "add"
tgt = "gt"
tgteq = "gteq"
teq = "eq"
tnot = "not"
if = "if"
tout = "out"
tend = "end"
point = "*"
comma = ","
number = <>
label = <>
comment = <> %ignore%
whitespace = <> %ignore%
%productions%
expression = atom [expression];
atom
= seteax
| moveax8esp
| setebx
| movebx8esp
| mov8espeax
| mov8espebx
| addesp
| addeaxebx
| gt
| gteq
| eq
| not
| ifeaxjmp
| jmp
| out
| end
| linelabel ;
seteax = set eax comma number;
moveax8esp = mov eax comma point esp;
setebx = set ebx comma number;
movebx8esp = mov ebx comma point esp;
mov8espeax = mov point esp comma eax;
mov8espebx = mov point esp comma ebx;
addesp = add esp comma number;
addeaxebx = add eax comma ebx;
gt = tgt;
gteq = tgteq;
eq = teq;
not = tnot;
ifeaxjmp = if eax tjmp label;
jmp = tjmp label;
out = tout eax;
end = tend;
linelabel = label;
生成**後,加入新建的 zasmc 工程,參照 grammatica 的例子除錯了一會兒,增加一些處理**後,編譯器可以正常工作了。用它編譯上一次的的 1 到 100 和的彙編**,發現幾個彙編**的格式錯誤還想再寫乙個程式驗證一下,fibonacci 序列是乙個不錯的例子,於是編寫 d 的原型如下:
import std.stdio;
static void main(char args)
void write(int n)
改寫為彙編**如下:
; 斐波那契
; esp i, esp+4 a, esp+8 b, esp+12 t
; int i=0;
set eax, 0
mov *esp, eax
; int a=1;
; write(a);
set eax, 1
add esp, 4 ; a
mov *esp, eax
out eax
; int b=1;
; write(b);
add esp, 4 ; b
mov *esp, eax
out eax
add esp, -8 ; i
; int t;
@next
; t = a + b;
; write(t);
add esp, 4 ; a
mov eax, *esp
add esp, 4 ; b
mov ebx, *esp
add eax, ebx
add esp, 4 ; t
mov *esp, eax
out eax
; a = b;
; b = t;
add esp, -4 ; b
mov eax, *esp
add esp, -4 ; a
mov *esp, eax
add esp, 8 ; t
mov eax, *esp
add esp, -4 ; b
mov *esp, eax
; i++;
add esp, -8 ; i
mov eax, *esp
set ebx, 1
add eax, ebx
mov *esp, eax
set ebx, 10 ; 迴圈次數
gteq
notif eax jmp @next
end
用 zasmc 編譯,生成 fibonacci.bin,載入到虛擬機器,第一次執行錯誤,後來發現是 d 轉彙編的時候的疏忽,修正彙編**後,編譯,載入執行,得到正確的結果。
下一步就是寫 z 的編譯器了,這一步可能要花比較長的時間,準備把 z 編譯成彙編**,然後再用這個彙編編譯器編譯成機器**,這樣,z 編譯器就不需要處理行號問題了。
下面是虛擬機器和彙編編譯器的源**,以及執行 fibonacci 的截圖:
組合語言編譯器 提高編譯器的彙編能力
很多軟體設計者都相信他們所編寫的彙編 比編譯器所產生的 效率更高 因此他們認為用組合語言所做的專案比用高階語言所做的專案要好 對這些工程師來說 組合語言所帶來的高效比前面所討論的c語言的優點重要得多 我相信如果這些工程師把他們所編寫的彙編 和用c語言編寫的程式通過編譯後產生的 比較一下 他們肯定會非...
組合語言 編譯器
乙個組合語言程式從寫出到最終執行的簡要過程 編寫 編譯 連線 執行 notepad 選擇assembly assume cs abc abc被我們當做 段來使用,so要把它和cs聯絡起來 abc segment 定義乙個段 abc 到ends結束 start mov ax,2 給程式乙個起始位置 a...
gcc編譯器(二)
靜態庫 工程在呼叫靜態庫時,複製靜態庫源 加長,不節省程式空間字尾名.a 優點 編譯後不需要再依賴庫 以空間換時間 動態庫 工程建立對映關係,每次呼叫都需要去庫中載入,字尾名為.so 共享庫 程式輕便,便於公升級。小tips 所有程式執行都在記憶體中,硬碟只能儲存程式。靜態庫的建立 gcc c 原始...