小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

淺析.NET MSIL代碼

 weijianian 2016-08-07


來源:Joye.Net

鏈接:http://www.cnblogs.com/yinrq/p/5486103.html


一、前言


IL是什么?


 Intermediate Language (IL)微軟中間語言


C#代碼編譯過程?


C#源代碼通過LC轉(zhuǎn)為IL代碼,IL主要包含一些元數(shù)據(jù)和中間語言指令;


JIT編譯器把IL代碼轉(zhuǎn)為機器識別的機器代碼。如下圖



語言編譯器:無論是VB code還是C# code都會被Language Compiler轉(zhuǎn)換為MSIL


MSIL的作用:MSIL包含一些元數(shù)據(jù)和中間語言指令


JIT編譯器的作用:根據(jù)系統(tǒng)環(huán)境將MSIL中間語言指令轉(zhuǎn)換為機器碼


為什么ASP.NET網(wǎng)站第一次運行時會較慢,而后面的執(zhí)行速度則會相對快很多?


當(dāng)你第一次運行.NET開發(fā)的站點時,CLR會將MSIL通過JIT進行編譯,最終轉(zhuǎn)換為執(zhí)行速度非常快的Native Code。這可以解釋。


為什么要了解IL代碼?


如果想學(xué)好.NET,IL是必須的基礎(chǔ),IL代碼是.NET運行的基礎(chǔ),當(dāng)我們對運行結(jié)果有異議的時候,可以通過IL代碼透過表面看本質(zhì);


IL也是更好理解、認識CLR的基礎(chǔ);


大量的實例分析是以IL為基礎(chǔ)的,所以了解IL,是讀懂他人代碼的必備基礎(chǔ),同時自己也可以獲得潛移默化的提高;


二、如何把ILDasm導(dǎo)入到VS中


想要看IL代碼需要使用ILDasm工具,工具一般在電腦的


C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\ildasm.exe


也可以下載ILSpy:http:///


把ILDasm導(dǎo)入到VS工具中,使用方便,具體如下:工具 - > 外部工具 


  


導(dǎo)入之后,vs工具里面就有ILDasm工具了。以后想看IL代碼方便多了。


IL代碼通過ILDasm反編譯后(左圖),ILDasm圖標意義(右圖)


  



三、分析IL代碼


在分析IL代碼之前,要先理解幾個概念:



圖片來源:https://msdn.microsoft.com/zh-tw/library/dd229210.aspx

Managed Heap(托管堆):這就是NET中的托管堆,用來存放引用類型,它是由GC(垃圾回收器自動進行回收)管理;


Call Stack(調(diào)用堆棧):調(diào)用堆棧:調(diào)用堆棧是一個方法列表,按調(diào)用順序保存所有在運行期被調(diào)用的方法。


Evaluation Stack(計算堆棧):每個線程都有自己的線程棧,IL 里面的任何計算,都發(fā)生在 Evaluation Stack 上,其實就是一個 Stack 結(jié)構(gòu)??梢?Push,也可以 Pop。


可以對照IL指令:指令列表,一步一步來分析IL代碼


1、用C#寫一個簡單控制臺應(yīng)用程序


using System;


namespace ILDemo

{

    class Program

    {

        static void Main(string[] args)

        {

            int i = 1;

            int j = 2;

            int k = 3;

            int answer = i + j + k;

            Console.WriteLine('i+j+k=' + answer);

            Console.ReadKey();

        }

    }

}


2、 用ILDasm打開bin下的.exe文件查看代碼,具體IL代碼如下:


.method private hidebysig static void  Main(string[] args) cil managed

{

  .entrypoint 

  // 代碼大小       42 (0x2a)

  .maxstack  2

  .locals init ([0] int32 i,

           [1] int32 j,

           [2] int32 k,

           [3] int32 answer)

  IL_0000:  nop

  IL_0001:  ldc.i4.1

  IL_0002:  stloc.0

  IL_0003:  ldc.i4.2

  IL_0004:  stloc.1

  IL_0005:  ldc.i4.3

  IL_0006:  stloc.2

  IL_0007:  ldloc.0

  IL_0008:  ldloc.1

  IL_0009:  add

  IL_000a:  ldloc.2

  IL_000b:  add

  IL_000c:  stloc.3

  IL_000d:  ldstr      'i+j+k='

  IL_0012:  ldloc.3

  IL_0013:  box        [mscorlib]System.Int32

  IL_0018:  call       string [mscorlib]System.String::Concat(object,

                                                              object)

  IL_001d:  call       void [mscorlib]System.Console::WriteLine(string)

  IL_0022:  nop

  IL_0023:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()

  IL_0028:  pop

  IL_0029:  ret

} // end of method Program::Main


3、會用到的IL指令:


nop:無操作


ret:從當(dāng)前方法返回,并將返回值(如果存在)從調(diào)用方的計算堆棧推送到被調(diào)用方的計算堆棧上。

call:調(diào)用由傳遞的方法說明符指示的方法。


box:將值類轉(zhuǎn)換為對象引用,就是裝箱,同理可以知道拆箱unbox

 

ldc.i4.X:把int32的值推送到計算堆棧


stloc.X:把計算堆棧頂部的值放到調(diào)用堆棧索引為X處


ldloc.X:把調(diào)用堆棧X處的值復(fù)制到計算堆棧


4、理解注釋后的代碼


.method private hidebysig static void  Main(string[] args) cil managed

{

  .entrypoint  //程序入口

  // 代碼大小       42 (0x2a)

  .maxstack  2    // 計算出計算堆棧的能存幾個值


  .locals init ([0] int32 i,

           [1] int32 j,

           [2] int32 k,

           [3] int32 answer) //定義int32類型的i,j,k,answer


  IL_0000:  nop   //無操作


  IL_0001:  ldc.i4.1  //把i的值放到計算堆棧上

  IL_0002:  stloc.0   //把計算堆棧頂部的值(i的值)放到調(diào)用堆棧索引0處

  IL_0003:  ldc.i4.2  //把j的值放到計算堆棧上

  IL_0004:  stloc.1   //把計算堆棧頂部的值(j的值)放到調(diào)用堆棧索引1處

  IL_0005:  ldc.i4.3  //把k的值放到計算堆棧上

  IL_0006:  stloc.2   //把計算堆棧頂部的值(k的值)放到調(diào)用堆棧索引2處


  IL_0007:  ldloc.0   //把調(diào)用堆棧索引為0處的值復(fù)制到計算堆棧 

  IL_0008:  ldloc.1   //把調(diào)用堆棧索引為1處的值復(fù)制到計算堆棧

  IL_0009:  add       //相加

  IL_000a:  ldloc.2   //把調(diào)用堆棧索引為2處的值復(fù)制到計算堆棧

  IL_000b:  add       //相加

  IL_000c:  stloc.3   //把計算堆棧頂部的值(add的值)放到調(diào)用堆棧索引3處

  IL_000d:  ldstr      'i+j+k='  //推送對元數(shù)據(jù)中存儲的字符串的新對象引用。

  IL_0012:  ldloc.3   //把調(diào)用堆棧索引為3處的值復(fù)制到計算堆棧


  IL_0013:  box        [mscorlib]System.Int32     //裝箱

  IL_0018:  call       string [mscorlib]System.String::Concat(object,object)   //調(diào)用內(nèi)部方法

  IL_001d:  call       void [mscorlib]System.Console::WriteLine(string)       //調(diào)用WriteLine

  IL_0022:  nop       //無操作

  IL_0023:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()  //調(diào)用ConsoleKey

  IL_0028:  pop      //無操作

  IL_0029:  ret      //return

} // end of method Program::Main


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多