標籤:

自己寫的COFF文件格式和編譯器生成的.obj文件一樣嗎?

自己寫的編譯器,想按照COFF文件格式,自己輸出COFF文件,COFF文件包含彙編代碼,將其等同於.obj文件,然後調用鏈接器生成可執行文件,可行嗎?


如果你要實用化,那麼該用 llvm來生成高性能機器碼,自己去弄 coff, obj是臟活累活,弄出來也沒太大意義。想簡單點可以輸出彙編給 nasm,或者用 asmjit之類的在內存裡面生成機器碼。

如果你是自己弄著玩,還是自己做一個虛擬機比較好玩,仿照 RISC指令集定義一個20個左右的指令集(不需要返照 intel的 cisc,太累了),RISC定址比較簡單,統一,比如只有 LDR/STR 兩條命令可以讀寫內存,加減乘除邏輯運算等,只能寄存器到寄存器。

然後再給你的 RISC虛擬機做一個簡單的腳本,類似彙編,然後讓你的編譯器輸出成 RISC彙編,交給虛擬機執行,多好玩,而且還可以加很多介面,讓你的腳本系統直接調用 C實現的各種功能,例如,我剛讀大學時候做著玩的遊戲編程語言+虛擬機:

提供遊戲功能的虛擬機在跑編譯出來的虛擬機彙編

腳本編譯成虛擬機彙編的效果。

流程相當於你要編譯兩次:

編譯器:腳本 -&> 虛擬機彙編

虛擬機:虛擬機彙編 -&> 指令位元組碼

最終運行是虛擬機直接在內存裡面跑你定義出來的 20條指令集的位元組碼。

開始設計虛擬機時,可以先在草稿紙上,把寄存器和 20條指令集(你可以仿照 arm, mips)推演清楚,然後設計位元組碼。設計完位元組碼以後,直接開始開發虛擬機,用一個數組作為虛擬機內存空間(指令+數據),然後徒手在數組裡面寫一些指令給虛擬機跑跑看,跑得通么。

指令裡面你留出一條來,用於調用外部服務,比如叫做 syscall,或者類似 intel的軟體中斷命令 int,然後外面使用虛擬機的用戶,可以用 C語言向虛擬機註冊新的中斷服務,實現功能擴充(比如實現 puts在控制台給定長度列印虛擬機寄存器所指向的字元串,和 PC上 Int 10h輸出字元串一樣)。

保證虛擬機能夠正常工作後,再給它設計一套精簡的彙編語言,以解析簡單為主,這部分實現可以直接放在虛擬機的 loader裡面,由虛擬機載入在內存中直接生成位元組碼。然後你可以用虛擬機彙編編寫一個 .vm的擴展名的文件,你的虛擬機可以直接載入 .vm並解釋成位元組碼運行。

這時候回過頭去改你的編譯器輸出部分,讓編譯器輸出成 .vm文件,然後就可以用虛擬機跑了。哪天你又實現一個新的腳本語言,還可以用你之前做的虛擬機來提供運行環境。

腳本系統編譯出來的符號,可以直接轉成.vm文件裡面的符號,比如腳本裡面函數 abc,在.vm文件裡面,叫做,_script_proc_abc,腳本裡面整數 x,叫做,_script_int_x。比如你從內存載入一個整數到寄存器,在 .vm裡面直接寫成 LDR R1, X 就行了,跳轉地址也是一樣。虛擬機的 loader載入 .vm文件的時候,可以把.vm和其依賴的其他.vm在內存中合併成一個大的 .vm文件(生成位元組碼後再合併也可以),再把符號表重定位成虛擬機內存空間裡面的指針地址。

最後,給你的腳本語言裡面,提供一條 ASM語句,可以直接寫虛擬機彙編。用腳本語言和ASM語句封裝一下虛擬機擴充出來的軟體中斷調用,成為腳本語言裡面的一個個基礎函數,作為你的標準庫。

你把虛擬機指令集定義並實現出來後,感覺象自己發明了顆 CPU,比直接生成coff, obj好玩多了。

----


RISC機器太複雜了。

你要真的自己實現虛擬機還是實現一個Stack-based吧,連寄存器分配都不用考慮。

或者其實可以編譯到brainf**k。

就是這樣。


linux上obj是elf格式

不過,嗯,coff可能可以識別


可以,不過推薦生成彙編文本然後丟給彙編器做後續工作


可以,但是生成彙編再調現成的彙編器會方便一點


推薦閱讀:

「Monokai」這個詞是什麼意思?
如何評價Tinyfool在swiftcon大會上發言跑題被罵一事?
為什麼好多編程「牛人」不喜歡用Microsoft Visual Studio?
隨著IDE的不斷升級,普通開發者的手工編碼是否會被完全取代?

TAG:編程 | 編譯器 |