詳解.net中IL語言

什麼是IL語言

中間語言,又稱(IL語言)。充當Clr與.net 平臺的中間語言,比如用C#編寫程序,編譯器首先是把C#代碼轉譯成IL語言,最終由Clr解釋執行,下面我們學習下IL語言。

如何讀懂IL語言

  • 寫一個helloworld的.net 程序,編譯運行完成。
      static void Main(string[] args)
      {
          Console.WriteLine("hello world");
      }
  • 使用ildasm.exe(C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools)反編譯代碼,得到IL代碼如下:
     .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint
        // 代碼大小       13 (0xd)
        .maxstack  8
        IL_0000:  nop
        IL_0001:  ldstr      "hello world"
        IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
        IL_000b:  nop
        IL_000c:  ret
      } // end of method Program::Main
  • 查找對應的指令表,來確定對應的含義

指令名稱

說明

Ldstr

推送對元數據中存儲的字符串的新對象引用。

Nop

如果修補操作碼,則填充空間。儘管可能消耗處理週期,但未執行任何有意義的操作。

Call

調用由傳遞的方法說明符指示的方法。

Ret

從當前方法返回,並將返回值(如果存在)從調用方的計算堆棧推送到被調用方的計算堆棧上。

  • 其它幾個名詞的的解釋 hidebysig: 與之對就的是hidebyname,這個是確定使用方法的簽名還是使用方法的名稱來確定調用哪個方法.
  • 整個的IL語言解釋
   .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint //代碼入口 
        // 代碼大小       13 (0xd)
        .maxstack  8  //整個程序的堆棧大小
        IL_0000:  nop  //無實在意義
        IL_0001:  ldstr      "hello world"  //定義字符
        IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)   //調用WriteLine變量
        IL_000b:  nop
        IL_000c:  ret  //返回
      } // end of method Program::Main

更復雜的Demo

  • 添加編寫如下C#代碼
 class Program
  {
      static void Main(string[] args)
      {
          var a = 0;
          var b = 1;
          var c = Add(a, b);
          Console.WriteLine(c.ToString());
      }

      public static int Add(int x,int y)
      {
          return x + y;
      }
  }
  • 生成相關的IL代碼及解釋
	.method private hidebysig static void  Main(string[] args) cil managed
	{
	.entrypoint
	// 代碼大小       27 (0x1b)
	.maxstack  2
	.locals init ([0] int32 a,
			[1] int32 b,
			[2] int32 c) //定義3個變量
	IL_0000:  nop
	IL_0001:  ldc.i4.0 //將整數值 0 作爲 int32 推送到計算堆棧上。
	IL_0002:  stloc.0  //從計算堆棧的頂部彈出當前值並將其存儲到索引 0 處的局部變量列表中。
	IL_0003:  ldc.i4.1 //將整數值 1 作爲 int32 推送到計算堆棧上。
	IL_0004:  stloc.1  //從計算堆棧的頂部彈出當前值並將其存儲到索引 1 處的局部變量列表中。
	IL_0005:  ldloc.0  //將索引 0 處的局部變量加載到計算堆棧上,這裏指a。
	IL_0006:  ldloc.1  //將索引 1 處的局部變量加載到計算堆棧上,這裏指b。
	IL_0007:  call       int32 ILTest.Program::Add(int32,
													int32)  //調用Add方法
	IL_000c:  stloc.2 //將索引 2 處的局部變量加載到計算堆棧上,這裏指c。 
	IL_000d:  ldloca.s   c  //將位於特定索引處的局部變量的地址加載到計算堆棧上(短格式)。
	IL_000f:  call       instance string [mscorlib]System.Int32::ToString() 
	IL_0014:  call       void [mscorlib]System.Console::WriteLine(string)
	IL_0019:  nop
	IL_001a:  ret
	} // end of method Program::Main

Add方法:

	.method public hidebysig static int32  Add(int32 x,int32 y) cil managed
	{
	// 代碼大小       9 (0x9)
	.maxstack  2
	.locals init ([0] int32 V_0) //創建一個V_0的局部變量
	IL_0000:  nop
	IL_0001:  ldarg.0 //將索引爲 0 的參數加載到計算堆棧上。
	IL_0002:  ldarg.1 //將索引爲 1 的參數加載到計算堆棧上。
	IL_0003:  add     //將兩個值相加並將結果推送到計算堆棧上。
	IL_0004:  stloc.0
	IL_0005:  br.s       IL_0007   //無條件地將控制轉移到目標指令(短格式)
	IL_0007:  ldloc.0    //將索引 0 處的局部變量加載到計算堆棧上。
	IL_0008:  ret
	} // end of method Program::Add

(本文完)

作者:老付 如果覺得對您有幫助,可以下方的訂閱,或者選擇右側捐贈作者,如果有問題,請在捐贈後諮詢,謝謝合作 如有任何知識產權、版權問題或理論錯誤,還請指正。 自由轉載-非商用-非衍生-保持署名,請遵循:創意共享3.0許可證 交流請加羣113249828: 點擊加羣 或發我郵件 [email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章