c#進階一:使用ILDASM來查看c#中間語言


  平時工作的時候總是使用ctrl c+ctrl v去快速開發實現業務功能,但是在工作之余,我們也應該要注意靜下心來去學習和提高自己。進階的文章隨性來寫,不定時更新。希望可以和大家共同學習,共同進步。今天我們一起來理解一下c#的運行機制。

  c#語言具有簡單易入門的特點,初學者通常簡單拖動幾個控件,寫幾行代碼就可以實現一個“程序”了,但是這樣也讓我們養成了一種依賴c#封裝特性的習慣。

  c#是一種高級語言,通過它編寫的代碼不能被機器識別。在這個被機器識別的過程中:首先是windows加載MSCorEE.dll(一個.NET framework自帶的鏈接庫,可在你安裝目錄找到),主線程會通過調用MSCorEE.dll中的方法來初始化CLR來獲取IL(即中間語言),但是,這時候的中間語言仍然不能被識別,還需要 JITCompiler 來將IL編譯成可以被機器識別的cpu指令,至此,我們在項目中生成的dll或者exe文件才算是被識別。

  接下來,我們來詳細探討怎么查看這個IL(中間語言)。

 一:在vs2015中增加ILDASM反編譯工具

  正所謂,工欲善其事,必先利其器。我們要想學習並且進階,就要學會運用各類工具。首先,我們將ILDASM加載到宇宙第一開發IDE -- VS中,博主此時使用的是vs2015,因此就以vs2015來作為例子。

  在vs2015中打開工具-->外部工具,點開后選擇添加,如圖:(一般來說,ILDASM默認地址是:C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools)

  二:反編譯后的IL詳細解釋

在安裝了ILDASM后,打開工具就可以看到已經多了一個工具ILDASM

我們在程序中使用這個工具。如下:

首先送上一張圖片幫助大家理解

 

1)雙擊打開MANIFEST,這是程序的清單文件。紅色箭頭表示引用的外部文件是mscorlib

.publickeytoken = (標記 ) 指定所引用程序集的實際公鑰標記。公鑰能唯一確定程序集。

.ver:指定引用程序集的版本

.assembly 表示程序集

 2)打開program的擴展

.class表示的Program是一個類,extends 代表Program類繼承於程序集mscorlib中的System.Object類,這就告訴我們,在C#中所有的類的父類都是Object。

private為訪問權限,表明該類是私有的。

auto:表明程序加載的時候內存布局是有CLR決定的,而不是由程序本身控制的。

ansi:表明類的編碼為ansi編碼

beforefieldinit :表明CLR可以在第一次訪問靜態字段之前的任何時刻執行類型構造函數。類型構造函數也就是構造函數,而使用beforefieldinit屬性可以提高性能。

 3)

.ctor 表示構造函數

cil managed 表明方法體中的代碼是IL代碼,且是托管代碼,即運行在CLR運行庫中的代碼

.maxstack 表明執行構造函數時,評估堆棧可容納數據項的最大個數。評估堆棧是保存方法中所需變量的值的一個內存區域,該區域在方法執行結束時會被清空,或者存儲一個返回值

IL_0000是代碼行的開頭。一般在IL_標記之前的部分為變量的聲明和初始化操作。

ldarg.0表明加載第一個成員參數,其中ldarg是load argument 的縮

call 指令一般用於調用靜態方法,而這段代碼中call指令並不是在調用靜態函數,而是調用System.Object構造函數。另外一個指令則一般用來調用實例方法,它的調用過程是:首先檢查被調用的函數是否為虛函數,

如果不是就直接調用,如果是則檢查子類是否重寫,如果有重寫就調用子類中的實現,如果沒有重寫就繼續調用原來函數。

ret 指令表示執行完畢,就是return的縮寫

4)看了這么久,終於到達了IL中間語言的Main方法

hidebysig :指令表示如果當前類作為父類,用該指令標記的方法將不會被子類繼承

.entrypoint :指令代表該函數是程序的入口函數,每個托管應用程序都有且只有一個入口函數,CLR加載的時候,首先從.entrypoint函數開始執行。

.locals init ([0] int32 i1,[1] int32 i2)

表示定義int類型的變量,變量名稱是:i1,i2

IL_0000: nop示不做任何操作 No Operation

IL_0001:ldc.i4.1:此指令的意思是:在 Evaluation Stack 置入一個個4 byte 的常數:  

stloc.0  :從計算堆棧的頂部彈出當前值並將其存儲到索引 0 處的局部變量列表中,在此示例中:stloc.0。此指令的意思是:從 Evaluation Stack 取出一個值,放到第 0 號變數(V0)中

ldloc.0 :將索引 0 處的局部變量加載到計算堆棧上。也就是:把變量helloString 加載到計算堆棧上(以ld為前綴的指令表示:入棧操作  st為前綴的指令則代表着出棧操作)

ldloc.1:同上,將索引 1處的局部變量加載到計算堆棧上。

 add:增加兩個變量的值

ret:返回結果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM