<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [你必須知道的.NET]第二十五回:認識元數據和IL(中)

      《你必須知道的.NET》網站 | Anytao技術博客 

      [你必須知道的.NET]第二十五回:認識元數據和IL(中)

      發布日期:2009.02.25 作者:Anytao
      ? 2009 Anytao.com ,Anytao原創作品,轉貼請注明作者和出處。

      說在,開篇之前
      書接上回[第二十四回:認識元數據和IL(上)],我們對PE文件、程序集、托管模塊,這些概念與元數據、IL的關系進行了必要的鋪墊,同時順便熟悉了以ILDASM工具進行反編譯的基本方法認知,下面是時候來了解什么是元數據,什么是IL這個話題了,我們繼續。

      很早就有說說Metadata(元數據)和IL(中間語言)的想法了,一直在這篇開始才算腳踏實地的對這兩個階級兄弟投去些細關懷,雖然來得沒有《第一回:恩怨情仇:is和as》那么迅速,但是Metadata和IL卻是絕對重量級的內容,值得我們在任何時間關注,本文就是開始。

                                                                                            www.anytao.com
       

      3 元數據是什么?

      元數據,就是描述數據的數據。這一概念并非CLR之獨創,Metadata存在于任何對數據和數據關系中,例如程序集清單信息也被稱為程序集元數據。而不同系統的元數據也相應具有本身的特點,.NET元數據也是如此。那么,CLR元數據描述的是哪些內容呢?正如前文的描述一樣,編譯之后,類型信息將以元數據的形式保存在PE格式文件中。.NET是基于面向對象的,所以元數據描述的主要目標就是面向對象的基本元素:類、類型、屬性、方法、字段、參數、特性等,主要包括:

      • 定義表,描述了源代碼中定義的類型和成員信息,主要包括:TypeDef、MehodDef、FieldDef、ModuleDef、PropertyDef等。
      • 引用表,描述了源代碼中引用的類型和成員信息,引用元素可以是同一程序集的其他模塊,也可以是不同程序集的模塊,主要包括:AssemblyRef、TypeRef、ModuleRef、MethodsRef等。
      • 指針表,使用指針表引用未知代碼,主要包括:MethodPtr、FieldPtr、ParamPtr等。
      • 堆,以stream的形式保存的信息堆,主要包括:#String、#Blob、#US、#GUIDe等。

      如前文所述,我們以ILDasm.exe可以通過反編譯的方式,通過執行Ctrl+M快捷鍵來獲取該程序集所使用的MetaData信息列表,在.NET中每個模塊包含了44個CLR元數據表,如下:

      表記錄 元數據表 說明
      0(0) ModuleDef 描述當前模塊
      1(0x1) TypeRef 描述引用Type,為每個引用到類型保存一條記錄
      2(0x2) TypeDef 描述Type定義,每個Type將在TypeDef表中保存一條記錄
      3(0x3) FieldPtr 描述字段指針,定義類的字段時的中間查找表
      4(0x4) FieldDef 描述字段定義
      5(0x5) MethodPtr 描述方法指針,定義類的方法時的中間查找表
      6(0x6) MethodDef 描述方法定義
      7(0x7) ParamPtr 描述參數指針,定義類的參數時的中間查找表
      8(0x8) ParamDef 描述方法的參數定義
      9(0x9) InterfaceImpl 描述有哪些類型實現了哪些接口
      10(0xa) MemberRef 描述引用成員的情況,引用成員可以是方法、字段還有屬性。
      11(0xb) Constant 描述了參數、字段和屬性的常數值
      12(0xc) CustomAttribute 描述了特性的定義
      13(0xd) FieldMarshal 描述了與非托管代碼交互時,參數和字段的傳遞方式。
      14(0xe) DeclSecurity 描述了對于類、方法和程序集的安全性
      15(0xf) ClassLayout 描述類加載時的布局信息
      16(0x10) FieldLayout 描述單個字段的偏移或序號
      17(0x11) StandAloneSig 描述未被任何其他表引用的簽名
      18(0x12) EventMap 描述類的事件列表
      19(0x13) EventPtr 描述了事件指針,定義事件時的中間查找表
      20(0x14) Event                描述事件
      21(0x15) PropertyMap          描述類的屬性列表
      22(0x16) PropertyPtr          描述了屬性指針,定義類的屬性時的中間查找表
      23(0x17) Property             描述屬性
      24(0x18) MethodSemantics      描述事件、屬性與方法的關聯
      25(0x19) MethodImpl           描述方法的實現
      26(0x1a) ModuleRef            描述外部模塊的引用
      27(0x1b) TypeSpec             描述了對TypeDef或者TypeRef的說明
      28(0x1c) ImplMap              描述了程序集使用的所有非托管代碼的方法
      29(0x1d) FieldRVA             字段表的擴展,RVA給出了一個字段的原始值位置
      30(0x1e) ENCLog               描述在Edit-And-Continue模式中哪些元數據被修改過
      31(0x1f) ENCMap               描述在Edit-And-Continue模式中的映射
      32(0x20) Assembly             描述程序集定義
      33(0x21) AssemblyProcessor    未使用
      34(0x22) AssemblyOS           未使用
      35(0x23) AssemblyRef          描述引用的程序集
      36(0x24) AssemblyRefProcessor 未使用
      37(0x25) AssemblyRefOS        未使用
      38(0x26) File                 描述外部文件
      39(0x27) ExportedType         描述在同一程序集但不同模塊,有哪些類型
      40(0x28) ManifestResource     描述資源信息
      41(0x29) NestedClass          描述嵌套類型定義
      42(0x2a) GenericParam         描述了泛型類型定義或者泛型方法定義所使用的泛型參數
      43(0x2b) MethodSpec           描述泛型方法的實例化
      44(0x2c) GenericParamConstraint 描述了每個泛型參數的約束

      然后是6個命名堆:

      說明

      #String 一個AscII string數組,被元數據表所引用,來表示方法名、字段名、類名、變量名以及資源相關字符串,但不包含string literals。
      #Blob 包含元數據引用的二進制對象,但不包含用戶定義對象
      #US 一個unicode string數組,包含了定義在代碼中的字符串(string literals),這些字符串可以直接由ldstr指令加載獲取,還記得嗎?我們在《第二十二回:字符串駐留(上)---帶著問題思考》中對字符串創建過程的論述嗎?
      #GUID 保存了128byte的GUID值,由元數據表引用
      #~ 一個特殊堆,包含了所有的元數據表,會引用其他的堆。
      #- 一個未壓縮的#~堆。除了#-堆,其他堆都是壓縮的。

      Note:對于#String和#US,一個簡單的區別就是:

      string hello = "Hello, World";

      變量hello名,將保存在#String,而代碼中字符串信息“Hello, World”則被保存在#US中。

      關于元數據信息的詳細描述,例如每個表包含哪些列,不同表間的關系,請參考[Standard ECMA-335]和[The .NET File Format]。

      在PE文件格式中,Metadata有著復雜的結構,我試圖以數據庫管理數據的角度出發來理解元數據的結構和關系,所以表示元數據的邏輯結構被成為元數據表,類似于數據庫表有主鍵和Sechema,元數據表以RID(表索引)和元-元數據表示類同的概念,以TypeDef表為例,通過數據引用關系同時與Field、Method、TypeRef等表發生關聯,其他表間又有類似的關系,從而形成一個復雜的類數據庫結構:

      因此,元數據是保存了類型的編譯后數據,是.NET程序運行的基礎,我們可以在運行時動態的以反射的方式獲取元數據信息,而這些信息在.NET Framework中以System.Type、MethodInfo等封裝,例如截取MSDN中一個類間關系的簡單示例:

      對于每個CLR類型而言都可以通過Object.GetType方法返回其Type,從而任意的取到所有的運行時元數據信息:

      // Release : code04, 2009/02/21                    
      // Author  : Anytao, http://www.anytao.com 
      // List    : Program.cs
      private static void ShowMemberInfo()
      {
          var assems = AppDomain.CurrentDomain.GetAssemblies();
      
          foreach (Assembly ass in assems)
          {
              foreach (Type t in ass.GetTypes())
              {
                  foreach (MemberInfo mi in t.GetMembers())
                  {
                      Console.WriteLine("Name:{0}, Type:{1}", mi.Name, mi.MemberType.ToString());
                  }
              }
          }
      }

      執行上述方法,將獲取一個長長的列表,看到很多熟悉的符號:-)

      4 IL是什么?

      IL,又稱為CIL或者MSIL,翻譯為中文就是中間語言,由ECMA組織(Standard ECMA-335)提供完整的定義和規范。顧名思義,中間語言正如它的名稱所言,任何與CLR兼容的編譯器所生成的都是中間語言代碼,這是實現CLR跨語言的基礎結構之一。IL就像一座橋梁,其指令集獨立于CPU指令而存在,可以由JIT編譯器在運行時翻譯為本地代碼執行,連接了任何遵守CLS規范的高級語言,為.NET平臺提供了最基本的支持。在[你必須知道的.NET]一書中,我用一整章(第3章 “一切從IL開始”)的篇幅對IL的基本內容進行了相應的介紹,所以關于IL的基礎內容例如基本類型、IL分析方法、常見指令、基本運算等,就不在本文有所贅述,只對IL基本內容進行一點小結:

      • IL是一種面向對象的機器語言,因此具有面向對象語言的所有特性,類、對象、繼承、多態等仍然是IL語言的基本概念。
      • IL指令獨立于CPU指令,CLR通過JIT編譯機制將其轉換為本地代碼。
      • IL和元數據是了解CLR運行機制的重要內容,對于我們打開CLR神秘面紗有著重要的意義。

      如前文[初次接觸]部分論述的一樣,可以通過ILDasm.exe或者Reflector工具對托管代碼執行反編譯來查看其IL代碼,對于很多情況下IL代碼分析可以解決很多高級語言隱藏的語法糖游戲,例如C#3.0提出的自動屬性、隱式類型、匿名類型、擴展方法等都可以很快從IL分析中找到答案,所以適當的了解IL是必要的。那么我們在下面JIT編譯時的一個片段來了解IL代碼對于托管程序執行的作用。

      另外,Metadata描述了靜態的結構,而IL闡釋了動態的執行,而IL代碼是通過一個4字節大小的地址引用元數據表的。該引用被稱為元數據符號(Metadata Token,也就是記錄元數據表的位置信息),在ILdasm.exe工具中選中“Show token values”,就可以在IL代碼中看到IL代碼通過Metadata Token引用元數據表的情況:

      .method /*06000003*/ private hidebysig static 
              void  Main(string[] args) cil managed
      {
        .entrypoint
        // Code size       36 (0x24)
        .maxstack  2
        .locals /*11000002*/ init ([0] int32 id,
                 [1] class Anytao.Insidenet.MetadataIL.One/*02000004*/ one,
                 [2] class Anytao.Insidenet.MetadataIL.Two/*02000002*/ two)
        IL_0000:  nop
        IL_0001:  ldc.i4.1
        IL_0002:  stloc.0
        IL_0003:  newobj     instance void Anytao.Insidenet.MetadataIL.One/*02000004*/::.ctor() /* 06000007 */
        IL_0008:  stloc.1
        IL_0009:  ldloc.1
        IL_000a:  ldloc.0
        IL_000b:  callvirt   instance void Anytao.Insidenet.MetadataIL.One/*02000004*/::set_ID(int32) /* 06000006 */
        IL_0010:  nop
        IL_0011:  newobj     instance void Anytao.Insidenet.MetadataIL.Two/*02000002*/::.ctor() /* 06000002 */
        IL_0016:  stloc.2
        IL_0017:  ldloc.2
        IL_0018:  callvirt   instance string Anytao.Insidenet.MetadataIL.Two/*02000002*/::SayHello() /* 06000001 */
        IL_001d:  call       void [mscorlib/*23000001*/]System.Console/*01000012*/::WriteLine(string) /* 0A000011 */
        IL_0022:  nop
        IL_0023:  ret
      } // end of method Program::Main

      其中,按照ECMA定義的規范,元數據第一個字節表示引用的元數據表,而其余三個字節則表示在相應元數據表中的記錄,例如06000003表示了引用了MethodDef(06)表的000003項Main方法。

      我們可以通過Type的MetadataToken屬性在運行時反射獲取類型的元數據符號,例如:

      static void Main(string[] args)
      {
          Console.WriteLine(typeof(One).MetadataToken);
      }

       

      有了上述所有的準備,我們就可以著手分析元數據和IL在程序執行時的角色和關聯。

      欲知后事如何,且聽下文繼續:-)

                                                                                            www.anytao.com


       

      anytao | ? 2009 Anytao.com | http://www.rzrgm.cn/anytao/archive/2009/02/25/must_net_25.html

      2009/02/25 | http://anytao.cnblogs.com/

      原文地址:

      本文以“現狀”提供且沒有任何擔保,同時也沒有授予任何權利。 | This posting is provided "AS IS" with no warranties, and confers no rights.

      本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

      參考文獻

      溫故知新

      [開篇有益]
      [第一回:恩怨情仇:is和as]
      [第二回:對抽象編程:接口和抽象類]
      [第三回:歷史糾葛:特性和屬性]
      [第四回:后來居上:class和struct]
      [第五回:深入淺出關鍵字---把new說透]
      [第六回:深入淺出關鍵字---base和this]
      [第七回:品味類型---從通用類型系統開始]
      [第八回:品味類型---值類型與引用類型(上)-內存有理]
      [第九回:品味類型---值類型與引用類型(中)-規則無邊]
      [第十回:品味類型---值類型與引用類型(下)-應用征途]
      [第十一回:參數之惑---傳遞的藝術(上)]
      [第十二回:參數之惑---傳遞的藝術(下)]
      [第十三回:從Hello, world開始認識IL]
      [第十四回:認識IL代碼---從開始到現在]
      [第十五回:繼承本質論]
      [第十六回:深入淺出關鍵字---using全接觸]
      [第十七回:貌合神離:覆寫和重載]
      [第十八回:對象創建始末(上)]
      [第十九回:對象創建始末(下)]
      [第二十回:學習方法論]
      [第二十一回:認識全面的null]
      [第二十二回:字符串駐留(上)---帶著問題思考]
      [第二十三回:品味細節,深入.NET的類型構造器]
      [第二十四回:認識元數據和IL(上)]

      posted @ 2009-02-25 00:54  Anytao  閱讀(7323)  評論(17)    收藏  舉報
      主站蜘蛛池模板: 高清在线一区二区三区视频| 97精品亚成在人线免视频| 日韩剧情片电影网站| 亚洲欧美日韩愉拍自拍美利坚| 精品一区二区三区日韩版| 偷拍激情视频一区二区三区| 吉川爱美一区二区三区视频| 搡bbbb搡bbb搡| 韩国免费a级毛片久久| 韩国主播av福利一区二区| 丁香五月亚洲综合在线国内自拍| 镇原县| 亚洲一区二区三成人精品| 亚洲成av人片无码天堂下载| 亚洲精品男男一区二区| 无码人妻一区二区三区av| 东北女人毛多水多牲交视频 | 九九热视频在线免费观看| 水蜜桃视频在线观看免费18| 亚洲中文字幕一区二区| 无码人妻精品一区二区三区下载| 久久成人影院精品777| 国产主播精品福利午夜二区| 色偷偷www.8888在线观看| 人妻少妇精品系列| 亚洲中文字幕一二区日韩| 国产久9视频这里只有精品| 久久精品蜜芽亚洲国产av| 色婷婷亚洲精品综合影院| 亚洲精品国产精品乱码不卡 | 中文字幕无码成人免费视频| 又黄又刺激又黄又舒服| 亚洲精品区二区三区蜜桃| 强奷乱码欧妇女中文字幕熟女| 四虎成人精品永久网站| 亚洲国产成人精品av区按摩| 国产精品女在线观看| 亚洲精品一区二区三天美| 成人婷婷网色偷偷亚洲男人的天堂| 亚洲激情视频一区二区三区| 久久亚洲精品11p|