溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

IL反編譯的實用工具Ildasm.exe的使用方法

發(fā)布時間:2020-07-07 09:12:05 來源:網絡 閱讀:1976 作者:zhou2228502811 欄目:編程語言

一.前言:

微軟的IL反編譯實用程序——Ildasm.exe,可以對可執(zhí)行文件(ex,經典的控制臺Hello World 的 exe 可執(zhí)行文件)抽取出 IL 代碼,并且給出命名空間以及類的視圖。在講述如何反編譯之前,有必要從虛擬CPU的角度來看CLR,這樣有助于先從正面了解代碼執(zhí)行過程。

虛擬CPU:

.NET 程序,其核心皆為 CLR ,而同時CLR的功能卻與CPU非常相近,其中CLR執(zhí)行IL代碼(或叫做,IL指令)、操作數據,只不過操作的代碼不同:CPU操作機器語言,而CLR操作IL代碼。

由上,上述講解的是從IL--機器語言的過程,而Ildasm則可以實現將可執(zhí)行程序(機器語言)--IL代碼,這就是Ildasm的主要功能。

在Anytao的《你必須知道的.NET》中對IL代碼專門做了說明,雖然暫時悟不透其"深遠意義",但我還是愿意去開始我的IL之旅的,呵呵~。在此我們先看,Anytao對于掌握(或者了解) IL代碼的重要性:

1.通用的語言基礎是.NET運行的基礎,當我們對運行結果有異議的時候,如何透過表面看本質,IL是必須的基礎;

2. IL也是更好理解、認識CLR的基礎;

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

有上述3條影響,足以讓任何一個有追求的人都鼓足勁,去開始IL之旅了(自然包括我,呵呵~)。

二 .Ildasm.exe 的使用方法:

在應用Ildasm.exe具體反編譯代碼之前,先附上MSDN對于用Ildasm.exe反編譯的經典幫助示例:

IL反編譯的實用工具Ildasm.exe的使用方法

然后我們用Ildasm.exe具體反編譯經典的"Hello World"控制臺程序的可執(zhí)行文件,展現出來的視圖為:

IL反編譯的實用工具Ildasm.exe的使用方法

分析具體IL代碼:

1.MANIFEST清單:

  MANIFEST是一個附加信息列表,主要包含程序集的一些屬性,如程序集名稱、版本號、哈希算法等;

2.ConsoleApplication1.Program類:

這才是我們介紹的主角。

首先是Program類:代碼為

.class private auto ansi beforefieldinit ConsoleApplication1.Program
       extends [mscorlib]System.Object
{
} // end of class ConsoleApplication1.Program

1).class,表示Program是一個類。并且它繼承自程序集—mscorlib的System.Object類;

2)private,表示訪問權限;

3)auto,表示程序的內存加載全部由CLR來控制;

4)ansi,是為了在沒有托管代碼與托管代碼之間實現無縫轉換。這里主要指C、C++代碼等;

5)beforefieldinit,是用來標記運行庫(CLR)可以在靜態(tài)字段方法生成后的任意時刻,來加載構造器(構造函數);

其次是 .otor方法,代碼為:

 

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       7 (0x7)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  ret
} // end of method Program::.ctor

 

1)cil managed:表示其中為IL代碼,指示編譯器編譯為托管代碼;

2).maxstack:表示調用構造函數.otor期間的評估堆棧(Evaluation Stack) ;

3)IL_0000:標記代碼行開頭;

4)ldarg.0:表示轉載第一個成員參數,在實例方法中指的是當前實例的引用;

5)call:call一般用于調用靜態(tài)方法,因為靜態(tài)方法是在編譯期就確定的。而這里的構造函數.otor()也是在編譯期就制定的。而另一指令callvirt則表示調用實例方法,它是在運行時確定的,因為如前述,當調用方法的繼承關系時,就要比較基類與派生類的同名函數的實現方法(virtual和new),以確定調用的函數所屬的Method Table;

6)ret:表示執(zhí)行完畢,返回;

最后是Main()方法,代碼為:

 

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       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

 

1) .entrypoint指令表示CLR加載程序時,是首先從.entrypoint開始的,即從Main方法作為程序的入口函數;

2)ldstr:表示將字符串壓棧,在這里就是將"Hello World."壓棧;

3)hidebysig:表示當把此類作為基類,存在派生類時,此方法不被繼承,同上構造函數;

至此,我們對IL代碼的一些指令有了了解,也縱觀了IL世界里的概況,呵呵~

常用IL指令擴展:

一:創(chuàng)建對象實例的IL指令

關于創(chuàng)建對象的在內存分配的機制,在《內存探尋1之——值類型和引用類型的內存分配機制》里有了詳細的介紹。而常用的創(chuàng)建對象的IL指令使我們更好理解對象的步驟。其主要有4種:

1.newobj: 用于創(chuàng)建引用類型的對象;

2:ldstr:用于創(chuàng)建String對象變量;

3.newarr:用于創(chuàng)建數組型對象;

4:box:在值類型轉換為引用類型的對象時,將值類型拷貝紙托管堆上分配內存;

二:通過IL代碼,更好地理解屬性

我們在C++中,在典型的類中,都會定義用于控制有效性輸入的Set()函數,以及用于不同方式顯示的Get()函數。然而在C#中,它將Get()函數和Set()結合在一起,剛開始難免會為之混淆。然而若通過 Ildasm.exe對程序反編譯后觀察屬性的本質,即可看到其執(zhí)行機制,如下圖示(注:選自互聯網):

IL反編譯的實用工具Ildasm.exe的使用方法

由我們前面的分析IL代碼的方法,以及上圖的展示,我們可以看到屬性被重新分為Get()函數和Set()函數。ex,屬性Name,被分解為get_Name()函數和set_Name(String s)函數。這樣我們對其本質就一目了然了!至于其屬性的特殊表示形式,只看做是Set()函數和Get()函數的完美結合體就可以了,這也是C#語言的優(yōu)美體現啊,呵呵~

綜述之,我們對反編譯工具Ildasm.exe有了一定認識,最主要的,我們通過它反編譯的IL代碼,對基本的IL指令有了一定的了解,也對以后的在把IL代碼作為有力工具使用的過程中,更向前了一步!然而,這些都還只是IL的基礎,需要繼續(xù)深入,呵呵~


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI