久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

[你必須知道的.NET]第十三回:從Hello, world開始認識IL

 joojo 2007-10-15

本文將介紹以下內(nèi)容:

  • IL代碼分析方法 
  • Hello, world歷史 
  • .NET學習方法論

 

1. 引言

1988年Brian W. Kernighan和Dennis M. Ritchie合著了軟件史上的經(jīng)典巨著《The C programming Language》,,我推薦所有的程序人都有機會重溫這本歷史上的經(jīng)典之作。從那時起,,Hello, world示例就作為了幾乎所有實踐型程序設(shè)計書籍的開篇代碼,,一直延續(xù)至今,,除了表達對巨人與歷史的尊重,本文也以Hello, world示例作為我們扣開IL語言的起點,,開始我們循序漸進的IL認識之旅,。

2. 從Hello, world開始

首先,當然是展示我們的Hello, world代碼,,開始一段有益的分享,。

using System;
using System.Data;

public class HelloWorld
{
    
public static void Main()
    {
        Console.WriteLine(
"Hello, world.");
    }
}

這段代碼執(zhí)行了最簡單的過程,向陌生的世界打了一個招呼,,那么運行在高級語言背后真相又是什么呢,,下面開始我們基于上述示例的IL代碼分析。 

3. IL體驗中心

對編譯后的可執(zhí)行文件HelloWorld.exe應(yīng)用ILDasm.exe反編譯工具,,還原HelloWorld的為文本MSIL編碼,,至于其工作原理我們期望在系列的后續(xù)文章中做以交代,我們查看其截圖為:

Anytao.com
 

 

由上圖可知,,編譯后的IL結(jié)構(gòu)中,,包含了MANIFEST和HelloWorld類,其中MANIFEST是個附加信息列表,,主要包含了程序集的一些屬性,,例如程序集名稱、版本號,、哈希算法、程序集模塊等,,以及對外部引用程序集的引用項,;而HelloWorld類則是我們下面介紹的主角。

3.1 MANIFEST清單分析

打開MANIFEST清單,,我們可以看到

從這段IL代碼中,,我們的分析如下:

  • .assembly指令用于定義編譯目標或者加載外部庫。在IL清單中可見,,.assembly extern mscorlib表示外部加載了外部核心庫mscorlib,,而.assembly HelloWorld則表示了定義的編譯目標。值得注意的是,,.assembly將只顯示程序中實際應(yīng)用到的程序集列表,,而對于加入using引用的程序集,如果并未在程序中引用,,則編譯器會忽略多加載的程序集,,例如System.Data將被忽略,,這樣就有效避免了過度加載引起的代碼膨脹。
  • 我們知道m(xù)scorlib.dll程序集定義managed code依賴的核心數(shù)據(jù)類型,,屬于必須加載項,。 例如接下來要分析的.ctor指令表示構(gòu)造函數(shù),從代碼中我們知道沒有為HelloWord類提供任何顯示的構(gòu)造函數(shù),,因此可以肯定其繼承自基類System.Object,,而這個System.Object就包含在mscorlib程序集中。
  • 在外部指令中還會指明了引用版本(.ver),;應(yīng)用程序?qū)嶋H公鑰標記(.publickeytoken),,公鑰Token是SHA1哈希碼的低8位字節(jié)的反序(如下圖所示),用于唯一的確定程序集,;還包括其他信息如語言文化等,。

 

  • HelloWorld程序集中包括了.hash algorithm指令,表示實現(xiàn)安全性所使用的哈希算法,,系統(tǒng)缺省為0x00008004,,表明為SHA1算法;.ver則表示了HelloWorld程序集的版本號,;
  • 程序集由模塊組成,, .module為程序集指令,表明定義的模塊的元數(shù)據(jù),,以指定當前模塊,。
  • 其他的指令還有:imagebase為影像基地址;.file alignment為文件對齊數(shù)值,;.subsystem為連接系統(tǒng)類型,,0x0003表示從控制臺運行;.corflags為設(shè)置運行庫頭文件標志,,默認為1,;這些指令不是我們研究的重點,詳細的信息請參考MSDN相關(guān)信息,。

3.2 HelloWorld類分析

首先是HelloWorld類,,代碼為:

.class public auto ansi beforefieldinit HelloWorld
       extends [mscorlib]System.Object
{
// end of class HelloWorld
  • .class表明了HelloWorld是一個public類,該類繼承自外部程序集mscorlib的System.Object類,。
  • public為訪問控制權(quán)限,,這點很容易理解。
  • auto表明程序加載時內(nèi)存的布局是由CLR決定的,,而不是程序本身
  • ansi屬性則為了在沒有被管理和被管理代碼間實現(xiàn)無縫轉(zhuǎn)換,。沒有被管理的代碼,指的是沒有運行在CLR運行庫之上的代碼,例如原來的C,,C++代碼等,。
  • beforefieldinit屬性為HelloWorld提供了一個附加信息,用于標記運行庫可以在任何時候執(zhí)行類型構(gòu)造函數(shù)方法,,只要該方法在第一次訪問其靜態(tài)字段之前執(zhí)行即可,。如果沒有beforefieldinit則運行庫必須在某個精確時間執(zhí)行類型構(gòu)造函數(shù)方法,從而影響性能優(yōu)化,,詳細的情況可以參與MSDN相關(guān)內(nèi)容,。 

然后是.ctor方法,代碼為:

.method public hidebysig specialname rtspecialname 
        instance 
void  .ctor() cil managed
{
  
// 代碼大小       7 (0x7)
  .maxstack  8
  IL_0000:  ldarg.
0
  IL_0001:  call       instance 
void [mscorlib]System.Object::.ctor()
  IL_0006:  ret
// end of method HelloWorld::.ctor
  • cil managed 說明方法體中為IL代碼,,指示編譯器編譯為托管代碼,。
  • .maxstack表明執(zhí)行構(gòu)造函數(shù).ctor期間的評估堆棧(Evaluation Stack)可容納數(shù)據(jù)項的最大個數(shù)。關(guān)于評估堆棧,,其用于保存方法所需變量的值,,并在方法執(zhí)行結(jié)束時清空,或者存儲一個返回值,。
  • IL_0000,,是一個標記代碼行開頭,一般來說,,IL_之前的部分為變量的聲明和初始化,。
  • ldarg.0 表示裝載第一個成員參數(shù),在實例方法中指的是當前實例的引用,,該引用將用于在基類構(gòu)造函數(shù)中調(diào)用,。
  • call指令一般用于調(diào)用靜態(tài)方法,因為靜態(tài)方法是在編譯期指定的,,而在此調(diào)用的是構(gòu)造函數(shù).ctor()也是在編譯期指定的,;而另一個指令callvirt則表示調(diào)用實例方法,它的調(diào)用過程有異于call,,函數(shù)的調(diào)用是在運行時確定的,,首先會檢查被調(diào)用函數(shù)是否為虛函數(shù),如果不是就直接調(diào)用,,如果是則向下檢查子類是否有重寫,如果有就調(diào)用重寫實現(xiàn),,如果沒有還調(diào)用原來的函數(shù),,依次類推直到找到最新的重寫實現(xiàn)。
  • ret表示執(zhí)行完畢,,返回,。

最后是Main方法,代碼為:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  
// 代碼大小       11 (0xb)
  .maxstack  8
  IL_0000:  ldstr      
"Hello, world."
  IL_0005:  call       
void [mscorlib]System.Console::WriteLine(string)
  IL_000a:  ret
// end of method HelloWorld::Main
  • .entrypoint指令表明了CLR加載程序HelloWorld.exe時,,是首先從.entrypoint方法開始執(zhí)行的,,也就是表明Main方法將作為程序的入口函數(shù),。每個托管程序必須有并且只有一個入口點。這區(qū)別于將Main函數(shù)作為程序入口標志,。
  • ldstr指令表示將字符串壓棧,,"Hello, world."字符串將被移到stack頂部。CLR通過從元數(shù)據(jù)表中獲得文字常量來構(gòu)造string對象,,值得注意的是,,在此構(gòu)造string對象并未出現(xiàn)在《第五回:深入淺出關(guān)鍵字---把new說透》中提到的newobj指令,對于這一點的解釋我們將在下一回中做簡要分析,。
  • hidebysig屬性用于表示如果當前類作為父類時,,類中的方法不會被子類繼承,因此HelloWorld子類中不會看到Main方法,。

接下來的一點補充:

  • 關(guān)于注釋,,IL代碼中的注釋和C#等高級語言的注釋相同,其實編譯器在編譯IL代碼時已經(jīng)將所有的注釋去掉,,所以任何對程序的注釋在IL代碼中是看不見的,。 

3.3 回歸簡潔

去粗取精,我們的IL代碼可以簡化,,下面的代碼是基于上面的分析,并去處不重要的信息,,以更簡潔的方式來展現(xiàn)的HelloWorld版IL代碼,詳細的分析就以注釋來展開吧,。

4. 結(jié)論

結(jié)束本文,,我們從一個點的角度和IL來了一次接觸,,除了了解幾個重要的指令含義,,更重要的是已經(jīng)走進了IL的世界,。通過一站式的掃描HelloWorld的IL編碼,,我們還不足以從全局來了解IL,,不過第一次的親密接觸至少讓我們太陌生,,而且隨著系列文章的深入我們將逐漸建立起這種認知,,從而提高我們掌握了解.NET底層的有效工具,。本系列也將在后續(xù)的文章中,,逐漸建立起這種使用工具的方法,,敬請關(guān)注,。

 


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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多