1. 程式人生 > >【IL】IL入門

【IL】IL入門

表達 runtime rgs CP c++編譯 www. oca 托管代碼 被子

1.IL基本介紹
1.1 CLR介紹
在介紹IL之前,先說一說CLR。CLR的全稱Commen Language Runtime 公共語言運行時。因為CLR的存在,使得多語言開發成為可能。下面給出一張圖片,解釋支持CLR的幾種語言的關系。

技術分享圖片

從上面的圖片可以看出,CLR其實是不關心開發人員用哪一種語言寫源代碼。這意味著在選擇編程語言時,應該選擇最容易表達自己意圖的語言。可用任何一種語言開發代碼,只要編譯器是面向CLR的就可以了。

Microsoft創建了好幾種面向CLR的語言編輯器,包括:C/C++、C#、Visual Basic、F#、Iron Python、Iron Ruby、IL編輯器,當然面向CLR的語言絕不止Miscrosoft提供的這幾種。

在上面的圖片,有一點值得提出,IL編譯器也是面向CLR的。雖然最終CLR會把托管模塊中的IL代碼編譯成本機CPU指令,但是IL編譯器本身也是面向CLR的,所以可以直接利用IL進行開發。查看 如何對C#程序進行反編譯,獲得更詳細的內容。

1.2 IL介紹

在上面介紹CLR概念的時候,知道了IL也是面向CLR的,IL的全稱是中間代碼(intermediate code),也稱為托管代碼(managed code)。所有面向CLR的編譯器,最終都會把相應的代碼編譯為托管模塊。註意,高級語言通常只公開了CLR全部功能的一個子集,然而,IL匯編語言是允許開發人員訪問CLR的全部功能的,例如:C++編譯的托管模塊,希望能夠在C#程序中調用,但是C++和C#可能由於支持的功能不一樣,在C#中有可能不會成功調用,反之,C#的程序可能在C++中也不會 成功調用,無論怎樣IL是支持的,也就是說IL是能夠全部訪問所有CLR功能的。如果在開發中,遇到一種語言不能解決的問題,可以考慮使用另一種語言,或是使用IL語言。

2.IL案例講解

在這裏筆者使用C#作為源代碼:

static void Main(string[] args)
{
            int num = 1;
            int num2 = 2;
            int num3 = 3;
            Console.WriteLine(num+num2+num3);
}

IL代碼為:

//hidebysig指令表示如果當前類為父類,用該指令標記的方法將不會被子類繼承
//cil managed表明方法體中的代碼是IL代碼,且是托管代碼,即運行在CLR運行庫上的代碼
.method private
hidebysig static void Main(string[] args)cil managed { .entrypoint //該指令代表該函數程序的入口函數。每一個托管應用程序都有且只有一個入口函數,CLR加載程序時,首先從.entrypoint函數開始執行。 .maxstack 2 //執行構造函數時,評估堆棧可容納數據項的最大個數。評估堆棧是保存方法中所需要變量的值的一個內存區域,該區域在方法執行結束時會被清空,或者存儲一個返回值。 .locals init ( [0] int32 num, [1] int32 num2, [2] int32 num3) //表示定義int類型的變量,變量名分別為num,num2,num3。存儲在調用棧。 L_0000: nop //No operation的意思,即沒有任何操作。 L_0001: ldc.i4.1 //將“1”壓入評估棧,此時“1”處於評估棧的棧頂。 L_0002: stloc.0 //此指令表示把值從評估棧中彈出,並賦值給調用棧的第0個變量num。 L_0003: ldc.i4.2 L_0004: stloc.1 L_0005: ldc.i4.3 L_0006: stloc.2 //從.locals init到L_0006,相當於C#代碼的為i,j,k賦值。 L_0007: ldloc.0 //取調用棧中位置為0的元素壓入評估棧(取i的值)。 L_0008: ldloc.1 //取調用棧中位置為1的元素壓入評估棧(取j的值)。 L_0009: add //做加法操作 L_000a: ldloc.2 //取調用棧中位置為2的元素壓入評估棧(取k的值)。 L_000b: add //做加法操作 L_000c: call void [mscorlib]System.Console::WriteLine(int32) //調用輸出方法 L_0011: nop //No Operation L_0012: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() //調用ReadKey方法 L_0017: pop //把評估棧的內容清空 L_0018: ret //return 標記返回值 } //Main方法結束

觀察上面的IL代碼,可以發現,匯編語言和高級語言的不一樣之處,在匯編語言中,聲明一個變量,首先要把變量名存儲, 然後把值壓入到棧堆中,最後把值彈出並且賦值給相應的變量。關於Il的指令詳細,可以查看 IL指令詳解。

【IL】IL入門