C# MSIL 我本人推薦看的一篇文章(我感覺寫的非常好)

來源:互聯網
上載者:User
本文將介紹以下內容:

  ·       IL程式碼分析方法 

  ·       IL命令解析 

  ·       .NET學習方法論

  1. 引言

  自從『你必須知道.NET』系列開篇以來,受到大家很多的關注和支援,給予了anytao巨大的鼓勵和動力。俱往昔,我發現很多的園友都把目光和焦點注意在如何理解IL代碼這個問題上。對我來說,這真是個莫大的好訊息,因為很明顯我們的思路慢慢的從應用向底層發生著轉變,技巧性的東西是一個方面的積累,底層的探索在我認為也是必不可少的修鍊。如果我們選擇了來關注這項修鍊,那麼我們就應該選擇如何來著手這項修鍊,首先關注anytao的『你必須知道的.NET』系列可以給你提供一個捷徑,少花一些功夫;其次對大師級的作品也應有更深入的瞭解,如《Applied Microsoft .NET Framework Programming》、《.NET本質論》;再次,就是像我一樣從部落格園和MSDN的知識庫中不斷的成長。呵呵,除了給自己做了個廣告之外,我認為不管是何種途徑,瞭解和認識IL代碼,對於我們更深刻的理解.NET和.NET應用之上的本質絕對有不一樣的收穫,這也就是本文研究和分享的理由。

   那麼,我們要瞭解IL代碼,就要知道瞭解IL的好處,時間對每個程式設計師來說都是寶貴的,你必須清楚自己投資的價值再決定投入的資本。對於.NET程式員來說,IL代碼意味著:

  ·       通用的語言基礎是.NET啟動並執行基礎,當我們對程式啟動並執行結果有異議的時候,如何透過本質看錶面,需要我們從本質入手來探索,這時IL是你必須知道的基礎;

  ·       中繼資料和IL語言是CLR的基礎,瞭解必要的中繼語言是深入認識CLR的捷徑;

  ·       大量的案例分析是以IL來揭密的,因此瞭解IL是讀懂他人代碼的必備基礎,可以給自己更多收穫。

 

   很明顯這些優越性足以誘惑我們花時間和精力涉獵其中。然而,瞭解了IL的好處,並不意味著我們應該過分的來關注IL,有人甚至可以洋洋洒洒的寫一堆IL代碼來實現一個簡單Hello world程式,但是正如我們知道的那樣,程式設計已經走過了幾十年的發展,如果純粹的陶醉在曆史中,除了腦子不好,沒有其他的解釋。不然看見任何代碼都以IL的角度來分析,又將走進另一個誤區,我們的宗旨是追求但不過分。

   因此,有了上述了應該瞭解的理由和不應該過分的基準,在擺正心態的前提下,本文開始以作者認為的方式來展開對IL代碼的認識,作者期望通過本文的闡述與分析使得大家都能對IL有個概觀之解,並在平時的項目實踐中使用這種方法通過瞭解自己的代碼來瞭解.NET。我想,這種方法應該是值得提倡和發揮的最佳實務,不知你信不信呢?呵呵。

  2. 使用工具

   俗話說,工欲善其事,必先利其器。IL的器主要就是ILadsm.exe和reflector.exe,這兩個工具都是瞭解IL的基礎,其原理都是通過反射機制來查看IL代碼。

  ·       ILadsm.exe

   開啟.NET Framework SKD 命令提示行,輸入ildasm斷行符號即可開啟,:

  

  是我們熟悉的《第十三回:從Hello, world開始認識IL》中的樣本,其中的樹形符號代表的意思,可以從MSDN的一張經典協助樣本來解釋,如所示:

 

  (圖表來源:MSDN)

  ·   

   Reflector是Lutz Roeder開發的一個讓人興奮的反編譯利器,目前的版本是Version 5.0.35.0,可以支援.NET3.0,其功能也相當強大,在使用上也較ILDASM更加靈活,:

  可以方便的反編譯為IL、C#、VB、Delphi等多種語言,是深入瞭解IL的最佳利器。

   在本文中我們以最簡單的ILadsm.exe為說明工具。

  3. 分析結構

   分析IL結構,就參閱《第十三回:從Hello, world開始認識IL》 ,已經有了大致的介紹,在此不需要進行過多的筆墨,實際上IL的本身的結構也不是很複雜,瞭解了大致的體系即可。

  4. 解析常用命令

   我們在瞭解了IL檔案結構的基礎上,通過學習常用的IL命令,就可以基本上對IL達到了瞭解不過分的標準,因此對IL常用命令的分析就是本文的重點和要點。我們通過對常用命令的解釋、樣本與分析,逐步瞭解你陌生的語言世界原來也很簡單。

   IL指令集包括了基礎指令集和物件模型指令集大概有近200多個,對我們來說消化這麼多的陌生指令顯然不是明智的辦法,就行進階語言的關鍵字一樣,我們只取其一瓢獨飲,抓大放小的革命傳統同樣是有效學習辦法,詳細的指令集解釋請下載[MSIL指令速查手冊]。

  4.1 newobj和initobj

   newobj和intiobj指令就像兩個兄弟,常常讓我們迷惑在其然而不知其所以然,雖然認識但是不怎樣清楚,這種感覺很鬱悶,下面就讓我們看看他們的究竟:

  代碼引入

 

  指令說明

  圖片看不清楚?請點擊這裡查看原圖(大圖)。

  深入分析

  從上面的代碼中,我們可以得出那些值得推敲的結論呢?

  MSDN給出的解釋是:newobj用於分配和初始化對象;而initobj用於初始化實值型別。

  那麼newobj又是如何分配記憶體,完成對象初始化;而initobj又如何完成對實值型別的初始化呢?

  顯然,關於newobj指令,在《第五回:深入淺出關鍵字---把new說透》中,已經有了一定的介紹,簡單說來關於newobj我們有如下結論:

  ·       從託管堆分配指定類型所需要的全部記憶體空間。

  ·       在調用執行建構函式初始化之前,首先初始化對象附加成員:一個是指向該類型方法表的指標;一個是SyncBlockIndex,用於進行線程同步。所有的對象都包含這兩個附加成員,用於管理對象。

  ·       最後才是調用建構函式ctor,進行初始化操作。並返回建立對象的引用地址。

  而initobj的作用又可以小結為:

  ·       構造新的實值型別,完成實值型別初始化。值得關注的是,這種構造不需要調用實值型別的建構函式。具體的執行過程呢?以上例來說,initobj MyStruct的執行結果是,將MyStruct中的參考型別初時化為null,而基元類型則置為0。

  因此,實值型別的初始化可以是:

//initobj方式初始化實值型別

initobj    Anytao.net.My_Must_net.IL.MyStruct

 

  同時,也可以直接顯示調用建構函式來完成初始化,具體為

     MyStruct ms = new MyStruct(123);

   對應於IL則是對建構函式cto的調用。

//調用建構函式方式初始化實值型別

call       instance void Anytao.net.My_Must_net.IL.MyStruct::.ctor(int32)

  ·       Initobj還用於完成設定對指定儲存單元的指標置空(null)。這一操作雖不常見,但是應該引起注意。

  由此可見,newobj和initobj,都具有完成執行個體初始化的功能,但是針對的類型不同,執行的過程有異。其區別主要包括:

  ·       newobj用於分配和初始化對象;而initobj用於初始化實值型別。因此,可以說,newobj在堆中分配記憶體,並完成初始化;而initobj則是對棧上已經分配好的記憶體,進行初始化即可,因此實值型別在編譯期已經在棧上分配好了記憶體。

  ·       newobj在初始化過程中會調用建構函式;而initobj不會調用建構函式,而是直接對執行個體置空。

  ·       newobj有記憶體配置的過程;而initobj則只完成資料初始化操作。

  關於對象的建立,還有其他的情況值得注意,例如:

  ·       Newarr指令用來建立一維從零起始的數組;而多維或非從零起始的一維數組,則仍由newobj指令建立。

  ·       String類型的建立由ldstr指令來完成,具體的討論我們在下文來展開。

  4.2 call、callvirt和calli

  call、callvirt和calli指令用於完成方法調用,這些正是我們在IL中再熟悉不過的幾個朋友。那麼,同樣是作為方法調用,這幾位又有何區別呢?我們首先對其做以概括性的描述,再來通過代碼與執行個體,進入深入分析層面。

 

  ·       call使用靜態調度,也就是根據參考型別的靜態類型來調度方法。

  ·       callvirt使用虛擬調度,也就是根據參考型別的動態類型來調度方法;

  ·       calli又稱間接調用,是通過函數指標來執行方法調用;對應的直接調用當然就是前面的:call和callvirt。

  然而,雖然有以上的通用性結論,但是對於call和callvirt不可一概而論。call在某種情況下可以調用虛方法,而callvirt也可以調用非虛方法。具體的分析我們在以後的文章中來展開,暫不做過多分析。   

  5. 結論

   本文從幾個重點的IL指令開始,力求通過對比性的分析和深入來逐步揭開IL的神秘與迷惑,正如我們在開始強調的那樣,本文只是個開始也許也是個階段,對IL的探求正如我自己的腳步一樣,也在繼續著,為的是在.NET的技術世界能夠有更多的領悟。作者期望通過不斷的努力逐漸和大家一起從IL世界探求.NET世界,在以後的討論中我們間或的繼續這個主題的不斷成長。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.