本文的代碼包以cosmos-12304.zip爲例(從這個包開始,COSMOS的內核算是有了個基本的雛形,就像是一顆大樹在出芽前會先長出龐大的根系,如今就要破土長出第一顆芽了)程序員
IL2CPU之於COSMOS就至關與GCC之於LINUX,查看COSMOS的源代碼,能夠發現沒有一行彙編代碼,就連BOOTLOADER也是使用C#語言來完成的,在COSMOS中很對與硬件相對應的類,如屏幕、鍵盤等,而後在編譯的時候再由IL2CPU識別出這些特定的類並轉換成機器指令代碼代碼。編程
因爲是純C#的開發環境,所以IL2CPU責任重大,須要實現C#語言的各類特性,包括對象的初始化、多態、事件、委託等等,固然到cosmos-12304爲止,這些特性尚未所有實現(後面的應該會一步一步的都實現,不過尚未看事後面的源代碼,只是猜想而已)。除此以外,IL2CPU還負責處理對.net的運行庫(這個運行庫並非.net framework,這個庫是COSMOS本身實現的與.net framework相似但要小不少不少的一個庫,之後再講這一部分)ide
cosmos-12304這個版本的代碼和如今最新的代碼在文件結構上有很大的差異,之因此文章從這個代碼包開始,是由於小弟從第一個源代碼包開始,一點一點的挪到這裏,我的感受從這裏開始終於能夠大體的抓住了COSMOS的開發思路,目前的COSMOS應該能夠分紅兩部,一部分是IL2CPU,一部分是操做系統內核。整個COSMOS項目是從IL2CPU開始的(從早期的代碼能夠看出,全都是在實現的編譯器的任務),先是讓IL2CPU能把簡單的C#程序編譯成本地程序以後,就開始實現操做系統內核,隨着項目的深刻,一遍擴展內核的功能,一遍完善IL2CPU編譯器,小弟估計到後期IL2CPU將會支持所有C#語言乃至整個MSIL語言的全部特性。函數
好了,廢話到這該來點實質性的東西了,cosmos-12304中先修改啓動項目爲這個工具
該項目調用了一段腳本用來編譯並啓動COSMOS的內核,腳本內容以下:學習
腳本位於cosmos-12304\Build\Cosmos\ISO目錄下,文件名爲Build.bat(其實就是一段批處理程序.........)。設置完後F5啓動,整個項目就開始運行了測試
成功運行的截圖以下:ui
運行方式爲把內核編譯生成ISO文件,而後使用QEMU虛擬機加載(關於運行如何啓動能夠參考小弟的上一篇文章,使用的工具不太同樣,可是流程是相同的)spa
好了,到這裏整個項目算是運行完成了(對!就只有兩行輸出,雛形......雛形,你們見諒,就至關於能夠輸出一個「hello world」了)操作系統
接下來看看IL2CPU是如何把C#代碼轉換成能夠獨立運行的操做系統內核的,痛苦的歷程開始了(小弟編譯原理和操做系統原理沒學好,分析這裏的代碼是在是太痛苦了)
從Build.bat文件中的腳本能夠看出,啓動的時候運行的是IL2CPU項目,直接來到該項目下,點開,查看,是一個CONSOLE類型的項目,直接來到Main函數裏面,分析源代碼能夠發現,IL2CPU項目根據-in輸入參數來肯定要編譯的程序集--此處輸入的項目爲Cosmos.Shell.Console項目--在Main函數中找到以下代碼:
主要關注這一句:
e.Execute(InputFile, TargetPlatform, br, MetalMode, DebugMode, BCLDir, Plugs);
此處e爲一個ENGINE類型的對象,在上邊有實例化的代碼,跳到Execute方法的定義處,函數內容以下........額,太長了就不列出來,有興趣的朋友能夠本身查看下源代碼J
能夠看到IL2CPU先獲取了Cosmos.Shell.Console程序集的信息,而後存到一個本地變量中,
mCrawledAssembly = AssemblyFactory.GetAssembly(aAssembly);
而後就能夠從這個變量中獲取程序集都另外引用了哪些程序集,再把引用到的程序集都添加到mCrawledAssembly變量內,在mCrawledAssembly內部使用一個List<AssemblyDefinition>類型的變量來存儲這些程序集,留到後面生成彙編代碼的時候使用(注:此處使用了MONO項目中的一些類,如AssemblyFactory、AssemblyDefinition等,求一份MONO的類庫文檔,英文的也行),除此以外還加載了Plugs(插件?),目前看來,Plugs就至關於COSMOS庫,COSMOS中對外部硬件的操做都經過Plugs(庫)來實現,目前只實現了CONSOLE這個類,也就是說,COSMOS內核中使用的CONSOLE類不是.net framework中的CONSOLE類,而是由CONSOLE內核從新實現了的,在CONSOLE內部調用特定的對象(之後分析)來實現輸出功能,固然CONSOLE實現的方法和屬性都與.net framework中的同樣,這樣在編程的時候只需直接使用.net framework來完成操做便可,等到了編譯階段IL2CPU會自動把相應的代碼轉換成COSMOS的內部實現從而脫離對.net framework庫的依賴。
我的猜想之後Plugs會擴展成一個像.net framework同樣的類庫,不過.net framework的類庫這麼龐大……恐怕……………
完成以上這些操做後,IL2CPU還會加入一些初始化運行時的函數:
完了以後會傳入內核程序的入口點,這就是爲何不少語言的程序都是以Main函數做爲程序入口點的緣由,由於編譯器內部定義的就是把程序跳到Main函數開始執行,若是想讓別的函數做爲開始函數,則在編譯器中就得作相應的修改,有時候這部份內容也交由鏈接器來處理(有關鏈接器和編譯器的做用在此推薦本書《程序員的自我修養—鏈接、裝載與庫》)
有興趣的朋友能夠跟進代碼裏面研究一下轉換的過程,小弟實在是頂不住了,看得眼花花、頭暈暈,你們知道是這麼一個流程就好,之後的編譯過程基本上就是走的這麼一個流程,下面是小弟總結出來的IL2CPU的編譯流程圖,歡迎你們拍磚:
從上圖中沒有看到傳統編譯器中還須要進行的語法、詞法、文法分析這幾步,嘿嘿,其實這些步驟在加載以前就都已經完成了,這是由於IL2CPU中加載的須要編譯的文件都是程序集文件,而.net中,能夠經過反射來查看程序集中的全部定義的函數、變量之類的內容,至關於.net已經幫咱們作完了語法、詞法、文法分析,並把分析的結果分門別類的存放在程序集裏了,咱們只須要經過反射功能來查看程序集中已經分類好的信息便可。其實,上圖中除了分析和彙編的操做,其餘的都是把各個須要用到的程序集中的函數、變量這些東西取出來,再補充上一些額外的初始化操做。而分析和彙編的任務就是把從各個程序集中取出函數、變量翻譯成本地CPU代碼。在IL2CPU內部,是經過逐條翻譯MSIL指令來完成的。
能夠點開看一下Indy.IL2CPU.IL.X86項目(最新的代碼包中好像已經被改名爲Cosmos.Complier.IL2CPU.IL.X86)
裏面對每一調MSIL指令都寫了一個與其對應的類,每個類就是專門負責把其本身翻譯成X86的指令。
上面的這些函數小弟跟進去看了一下,在此以目前的水平就展開分析,展開了也說不清,但裏面的東西確實都是精華,雖然複雜了點,可是對於學習面向對象程序的結構和編譯器實現的朋友來講是一個很好的例子,在此推薦
最後,IL2CPU再使用第三方工具,把彙編出來的彙編指令文件轉換成本地CPU識別的二進制文件,代碼以下:
最後,在經過腳本,講二進制文件轉換成ISO文件供虛擬機加載運行:
@REM ----------- Build ISO
del cosmos.iso
attrib files\boot\grub\stage2_eltorito -r
..\..\..\Tools\mkisofs\mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o Cosmos.iso files
pause
@REM ----------- Start QEMU
cd ..\..\..\tools\qemu\
qemu.exe -L . -cdrom ..\..\build\Cosmos\ISO\Cosmos.iso -boot d
pause
最後附上一個comos-12304.zip中IL2CPU相關項目的說明(固然也是我的學習的總結,可能有錯,僅當參考,歡迎拍磚)
IL2CPU:IL2CPU的啓動項目
IL2CPU.Tests:用來測試對MSIL的指令的翻譯是否正確的測試項目
IL2CPUGUI:暫時無用
Indy.IL2CPU:IL2CPU的編譯引擎,主要的活動都發生在這裏面,同時封裝了用來實現MSIL特性的類,如垃圾收集器、多態等
Indy.IL2CPU.Assembler:實現彙編器的一些基類和一些通用的指令操做
Indy.IL2CPU.Assembler.X86:X86彙編器,封裝X86指令的實現
Indy.IL2CPU.Assembler.X86.Native:對X86彙編器的一些擴展,應該是用來封裝一些平臺特有的指令
Indy.IL2CPU.Assembler.X86.Win32:對X86彙編器的擴展,用來翻譯支持WIN32環境下的彙編程序
Indy.IL2CPU.IL:封裝MSIL指令的一些基類和一些通用的操做
Indy.IL2CPU.IL.X86:與Indy.IL2CPU.Assembler.X86項目配合,把MSIL指令翻譯成X86指令
Indy.IL2CPU.IL.X86.Native:與Indy.IL2CPU.Assembler.X86.Native項目配合,把MSIL指令翻譯成一些平臺支持的特有一些特性的指令
Indy.IL2CPU.IL.X86.Win32:與上面兩個相似,翻譯成Win32環境下的彙編指令
Indy.IL2CPU.Plugs:封裝一些用來在編譯的時候處理Plugs的類和操做
最新的代碼包中,以上項目的名字已經被該動,不過也只是前綴進行了改變,面的部分基本上都同樣。同時我的以爲IL2CPU也仍是很不錯的編譯器,學習編譯原理的朋友門,小弟在次推薦一下能夠研究一下IL2CPU的源代碼,也能夠寫些文章出來幫小弟解惑一下,呵呵J
好了,先寫到這裏吧,水平有限,寫得不是很好,留下的一些問題特別是關於Plugs的內容小弟也會在之後對源碼的學習中慢慢解開
若是以爲本文有點幫助的朋友樓主是很樂意接收鼓勵的J,能夠到樓主的淘寶充值店光顧下(歡迎收藏小店……廣告….廣告,你們懂的~~~~)或者點擊下博客裏面的廣告,呵呵
有大蝦路過的話樓主也願意接受雞蛋和板磚。