當前位置:編程學習大全網 - 源碼下載 - 什麽叫中間語言

什麽叫中間語言

中間語言MSIT

在.Net框架中,公***語言基礎結構使用公***語言規範來綁定不同的語言。通過要求不同的語言至少要實現公***類型系統(CTS)包含在公***語言規範中的部分,公***語言基礎結構允許不同的語言使用.Net框架。因此在.Net框架中,所有的語言(C#,VB.Net,Effil.Net等)最後都被轉換為了壹種通用語言:微軟中間語言(MSIL)。

MSIL是將.Net代碼轉化為機器語言的壹個中間過程。它是壹種介於高級語言和基於Intel的匯編語言的偽匯編語言。當用戶編譯壹個.Net程序時,編譯器將源代碼翻譯成壹組可以有效地轉換為本機代碼且獨立於CPU 的指令。當執行這些指令時,實時(JIT)編譯器將它們轉化為CPU特定的代碼。由於公***語言運行庫支持多種實時編譯器,因此同壹段MSIL代碼可以被不同的編譯器實時編譯並運行在不同的結構上。從理論上來說,MSIL將消除多年以來業界中不同語言之間的紛爭。在.Net的世界中可能出現下面的情況:壹部分代碼可以用Effil實現,另壹部分代碼使用C#或VB完成的,但是最後這些代碼都將被轉換為中間語言。這給程序員提供了極大的靈活性,程序員可以選擇自己熟悉的語言,並且再也不用為學習不斷推出的新語言而煩惱了。

解密微軟中間語言的系列文章將通過壹些簡單易懂的方式來揭示中間語言的復雜原理。這些原理通過詳細的例子來闡述。在壹些例子中同時給出了源代碼和中間代碼,通過比較源代碼和中間代碼,我們可以更好地理解編譯器的局限性,指導我們編寫出更好更快的代碼。

微軟中間語言概述 1.用中間語言編寫的壹個簡單程序

讓我們從經典的Hello World例子開始。首先在壹個文本編輯器中輸入以下的代碼,並保存為HelloWorld.il:

.assembly HelloWorldIL {}

.method static void HelloWorld() {

.entrypoint

ldstr "Hello World."

call void [mscorlib]System.Console::WriteLine(class System.String)

ret

}

在壹個中間語言程序中,如果某壹行以“.”開始,則代表這是壹個傳輸給匯編工具的指令,該指令要求匯編工具執行某些操作,例如生成壹個函數或類。而沒有以“.”開始的行是中間語言的代碼。在中間語言中方法通過匯編命令method來定義,匯編命令後跟方法的返回值、名稱和參數。方法體被包含在{}中。例子中的ret代表該方法的結束。

壹個中間語言文件可以包含很多函數,匯編工具沒有辦法分辨應該首先執行哪壹個方法。在諸如C#或VB這壹類高級語言中,程序的入口方法通常都有特定的名稱,例如在C#中的public static void Main()。這就是上面的匯編工具發出錯誤提示的原因。在中間語言中,第壹個被執行的方法被稱為入口函數(EntryPoint Function)。為了告訴匯編工具HelloWorld是入口函數,我們需要在代碼中增加壹條匯編命令entrypoint,該命令可以放在方法體中的任何位置。需要註意的是在壹個程序集中只能有壹個入口函數。

中間語言代碼通常被編譯成壹個模塊,該模塊隸屬於壹個程序集。在.Net中模塊和程序集的概念非常重要,因此開發人員需要很清楚地了解它們。在後面的文章中我們將詳細討論.Net程序的結構。通過在代碼中加入assembly命令,可以告訴匯編工具中間代碼隸屬於那個程序集。assembly命令的格式如下:

.assembly <程序集名稱> {}

需要註意在method命令後加入了static關鍵字,這是因為每個入口函數必須是靜態的,例如在C#中我們將Main方法定義為public static void Main()。

接下來我們需要調用WriteLine方法將HelloWorld字符串輸出到屏幕。通過使用call指令(Instruction)我們可以達到這個目的。指令的格式如下:

call <return type> <namespace>.<class name>::<method name>

這裏我們可以看到當調用壹個方法時,中間語言和其他的編程語言有很大的區別。在中間語言中,如果需要調用壹個方法,需要指定方法的全名,包括他的名稱域(namespace)、類名、返回值類型和參數的數據類型。這樣就保證了匯編工具能夠找到正確的方法。

在調用WriteLine方法時需要壹個字符串參數。所有傳遞給方法或函數的參數都被保存在內存的堆棧中。在中間語言中有壹個指令ldstr可以從堆棧中加載壹個字符串。(堆棧是內存中的壹塊區域,它被用於將參數傳輸給方法,在後面我們會詳細討論堆棧的問題)。所有的方法都從堆棧中獲取它們的參數,因此ldstr指令是必不可少的。ldstr指令的格式如下所示:

ldstr <parameter string>

我們可以用ILAsm.exe來編譯這個程序。在運行ILAsm.exe之前,首先需要確認壹下該程序已經包含在了Windows操作系統的Path環境變量中。ILAsm.exe 可在下面的路徑中找到:

%windir%\Microsoft.NET\Framework\v1.0.xxxx

其中xxxx是正在使用的.NET框架的內部版本號。例如我使用的版本號是3705,則應該如下設置Path環境變量:

Set Path = %Path%;c:\Windows\Microsoft.NET\Framework\v1.0.3705

然後運行cmd.exe(開始->運行->輸入cmd->按下確認鍵)。在彈出的命令窗口中輸入:

J:\Testcode>ilasm HelloWorld.il

匯編代碼後運行程序就可以看到Hello World.的輸出。

通過上面的例子,我們了解了中間語言的程序結構,壹些命令和指令。同時需要提醒大家的是中間語言是區分大小寫的。

2.改進的HelloWorld例子

在.Net中的所有語言都是面向對象的語言,但是上面的HelloWorld例子是壹個結構化的例子。下面讓我們來看壹下如何將它轉化為面向對象的代碼。在面向對象的編程中,我們將操作定義在類中。為了將上面的HelloWorld例子轉化為面向對象的代碼,可以使用class命令:

.class HelloWorld { }

class命令後緊跟的是類的名稱。類的名稱在中間語言中是可選的。同時我們還需要為該指令添加壹些屬性,例如存取控制類在內存中的布局和互用性等。這樣代碼就變成了:

.assembly HelloWorldIL {}

.class public auto ansi HelloWorld extends [mscorlib]System.Object {

.method public hidebysig static void HelloWorld() cil managed {

.entrypoint

ldstr "Hello World."

call void [mscorlib]System.Console::WriteLine(class System.String)

ret

}

.method public hidebysig specialname rtspecialname instance void .ctor() cil managed {

ldarg.0

call instance void [mscorlib]System.Object::.ctor()

ret

}

}

在代碼中用到了三個屬性:

· public:public是訪問控制屬性,它表明了對於訪問該類的成員沒有限制。

· auto:auto屬性表明了當類被加載到內存中時,在內存中的布局是由公***運行庫而不是程序決定的。

· ansi:指定ansi屬性是為了在沒有被管理和被管理的代碼之間實現無縫的轉化。在.Net中,那些不可直接應用在公***語言基礎設施之上的代碼被稱為沒有被管理的代碼,例如C、C++和VB6的代碼。我們需要壹個屬性來處理被管理的代碼和沒有被管理的代碼之間的互用性。在被管理的代碼中,字符串用雙字節的Unicode字符表示,而在被管理的代碼中,字符串有可能用單字節的ANSI字符表示。指定了ansi屬性就可以在不同的代碼間轉化字符串了。

我們知道在.Net框架中,所有的類都直接或間接地繼承了System.Object類。在代碼中我們明確指定了HelloWorld繼承了System.Object。

在HelloWorld方法中加入了public、hidebysig、cil managed屬性,下面是對這些屬性的解釋:

· public:在C#或VB.Net中,當我們定義壹個方法時,需要指定方法的訪問修飾符。訪問修飾符可以是public、protected、internal或private 。

· hidebysig:壹個類可以繼承其他的類,hidebysig屬性保證當前類中的方法在作為父類時不會被子類繼承。例如如果HelloWorldChild類繼承了HelloWorld類,在HelloWorldChild中不會看到HelloWorld方法。

· cil managed:該屬性將在後面討論。

在高級語言中(C#,VB.Net等),每個類必須有構造函數,而且構造函數的第壹行需要調用基類的構造函數。如果類中沒有構造函數,基類的構造函數將被自動調用。通常這是由編譯器自動完成的,現在我們要在的代碼中加入構造函數,該構造函數通過.ctor命令調用基類的構造函數。

小結

本文我們從經典的Hello World例子開始,通過實例了解了微軟中間語言的基本語法規則以及中間語言與其他開發語言的關系。在下壹篇文章中,我們將在此基礎上,運用實例程序講述.net應用程序的格式和結構等內容。

  • 上一篇:徐剛的低調求存
  • 下一篇:vivo手機升級後,指紋識別不能用了。我該怎麽辦?
  • copyright 2024編程學習大全網