2010-04-12 56 views
1

我已經爲我的編程語言(教育)創建了一個解釋器,現在我想進一步爲它創建一個編譯器。我知道這是非常艱苦的工作。爲Win32編寫編譯器的知識

我已經知道的是:

  • 我需要翻譯我的輸入語言彙編

了很多,是不是?現在我不知道的是:

  • 什麼彙編我需要創建Win32 PE可執行文件,例如,Visual Studio呢?
  • 文件頭怎麼樣?

我不想使用MASM,但它似乎我必須。

  • 如何將彙編器與我的編譯器結合?
+1

查看http://stackoverflow.com/questions/1669/learning-to-write-a-compiler – 2010-04-12 16:53:33

回答

1

您並不嚴格需要將您的代碼轉換爲程序集;你可以將它翻譯成任何語言,該語言可以編譯爲本機可執行文件。

讓我們來看一個非常簡單的例子。假設我有一些毫無價值的虛構語言(以下稱爲Adder),其中輸入文件包含任意數量的行,每行包含空格分隔的整數列表。輸出是每行的總和。

所以對於輸入文件

1 
1 2 3 
200 50 6 

輸出將

1 
6 
256 

您可以在Ruby中的一行寫解釋的加法:

puts($_.split.map(&:to_i).inject(0, :+)) while gets 

如果我想將輸入程序翻譯爲獨立的Ruby腳本,該怎麼辦? T'很簡單:

while line = gets 
    num = line.split.map(&:to_i).inject(0, :+) 
    puts "puts(#{num})" 
end 

輸出:

$ ruby adder2rb.rb nums.txt 
puts(1) 
puts(6) 
puts(256) 
$ ruby adder2rb.rb nums.txt | ruby - 
1 
6 
256 

好了,現在如果我們想這個翻譯的東西,實際上編譯爲本地可執行程序 - 比如,C?我們幾乎沒有任何改變:

puts '#include <stdio.h>' 
puts 'int main() {' 

while line = gets 
    num = line.split.map(&:to_i).inject(0, :+) 
    puts " printf(\"%ld\\n\", #{num}L);" 
end 

puts ' return 0;' 
puts '}' 

屆輸出:

$ ruby adder2c.rb nums.txt 
#include <stdio.h> 
int main() { 
    printf("%ld\n", 1L); 
    printf("%ld\n", 6L); 
    printf("%ld\n", 256L); 
    return 0; 
} 
$ ruby adder2c.rb nums.txt | tcc - 
$ ./a.out 
1 
6 
256 

(這裏注意,tccTiny C Compiler,這可能是,如果你希望最終用戶能夠生成你的項目非常有用可執行文件)。

想翻譯爲另一種高級語言嗎?哈斯克爾呢?

$ cat adder2hs.rb 
puts 'main = do' 

while line = gets 
    num = line.split.map(&:to_i).inject(0, :+) 
    puts " print #{num}" 
end 
$ ruby adder2hs.rb nums.txt 
main = do 
    print 1 
    print 6 
    print 256 
$ ruby adder2hs.rb nums.txt | runghc 
1 
6 
256 

當然,具有多個構造的任何語言的代碼翻譯將比上述例子顯着更完整;但是,基本思想保持不變,您將擁有針對輸出語言的一般模板。

現在,如果您決定仍然真的想要生成程序集而不是高級代碼,那麼您並不侷限於那裏的單個實現。比直接裝配更容易轉化爲虛擬機的字節碼。 MSIL會爲您提供.NET可執行文件,或者您可以使用LLVM的代碼生成工具。如果Java更多,你可以發出JVM字節碼。一個稍微不太常見的選擇是Parrot

在這些虛擬機中,只有AFAIK的LLVM纔會生成實際的本機可執行文件,但這可能不是您現在最關心的問題。

+0

+1給答案! – jimsweb 2012-03-04 16:45:07