日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

      歡迎訪問 生活随笔!

      生活随笔

      當前位置: 首頁 > 编程语言 > asp.net >内容正文

      asp.net

      [你必须知道的.NET]第二十四回:认识元数据和IL(上)

      發布時間:2023/12/10 asp.net 45 豆豆
      生活随笔 收集整理的這篇文章主要介紹了 [你必须知道的.NET]第二十四回:认识元数据和IL(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
      說在,開篇之前
      很早就有說說Metadata(元數據)和IL(中間語言)的想法了,一直在這篇開始才算腳踏實地的對這兩個階級兄弟投去些細關懷,雖然來得沒有《第一回:恩怨情仇:is和as》那么迅速,但是Metadata和IL卻是絕對重量級的內容,值得我們在任何時間關注,本文就是開始。?

      ??????????????????????????????????????????????????????????????????????????????????????www.anytao.com

      1 引言

      你可曾想到,我們的C#代碼,編譯之后究竟為何物?你可曾認知,我們的可執行程序,運行之時的軌跡究竟為哪般?那么,本文通過對Metadata(元數據)和IL(Intermediate Language, 中間語言)的認識開始,來逐步給出答案。在這個探索軌跡上,元數據、IL、程序集、程序域、JIT、虛分派、方法表和托管堆這些形形色色的神秘嘉賓將在某個時刻不期而遇,作為你必須知道的.NET?系列2.0版本的一部分,本文首先從認識元數據和IL這兩位重量級選手開始,而其他的嘉賓也將很快登場。

      2 初次接觸

      在事實上,編譯之后的cs代碼被組織為兩種基本的元素:元數據(Metadata)和IL。我們可以以最簡單的方式來了解程序集(*.dll)或可執行文件(*.exe)中包含的Metadata和IL的秘密,這種方式就是我們常說的反編譯,打開ILDasm并加載實現準備的程序集,我們可以看到托管PE文件的相關內容:

      詳細的結構信息和IL代碼分析,可以參見[你必須知道的.NET]第3章 “一切從IL開始”的介紹,在此就不做太多的分析。另外,我們可以通過執行“View/MetaInfo/Show!”或者Ctrl+M快捷鍵來獲取該程序集所使用的MetaData信息列表:

      ?

      其中該程序集使用的元數據主要有:Module、TypeRef、TypeDef、Method、Param、MemberRef、CostomAttribute、Assembly、AssemblyRef等,同時還包括#Strings、#GUID、#Blob、#US堆等。

      當然,關于ILDasm工具,還有很多好玩的使用方式來滿足我們探索IL代碼的好奇心,例如:

      ? ildasm Anytao.Insidenet.MetadataIL.exe /output:my.il,將反編譯結果導出為il代碼格式,生成一個my.il包含了所有的IL代碼和一個my.res包含了所有的資源文件。

      ? ildasm Anytao.Insidenet.MetadataIL.exe /text,將反編譯結果以Console形式輸出。

      當然我們還是推薦以GUI形式來查看IL細節,組織結構良好的Class View:

      ? ildasm Anytao.Insidenet.MetadataIL.exe

      下面首先給出參與編譯的相關代碼文件,然后再展開我們對Metadata和IL的討論:

      //?Release?:?code01,?2009/02/12????????????????????
      //?Author??:?Anytao,?http://www.anytao.com
      //?List????:?One.cs
      public?class?One
      {
      ????public?int?ID?{?get;?set;?}
      }//?Release?:?code02,?2009/02/12????????????????????
      //?Author??:?Anytao,?http://www.anytao.com
      //?List????:?Two.cs
      public?class?Two
      {
      ????public?string?SayHello()
      ????{
      ????????return?"Hello,?world.";
      ????}
      }//?Release?:?code03,?2009/02/12????????????????????
      //?Author??:?Anytao,?http://www.anytao.com?
      //?List????:?Program.cs
      class?Program
      {
      ????static?void?Main(string[]?args)
      ????{
      ????????int?id?=?1;
      ????????One?one?=?new?One();
      ????????one.ID?=?id;
      ????????Two?two?=?new?Two();
      ????????Console.WriteLine(two.SayHello());
      ????}
      }

      接著,我們對上述程序的編譯執行過程進行一點探索,以命令行編譯器來演化其大致的編譯過程,以此進一步了解托管模塊,程序集和可執行文件之間的關系:

      ?

      ?

      • 打開Visual Studio 2008 Command Prompt,并定位到cs代碼所在文件夾,編譯One.cs為托管模塊,執行命令:?
        ? csc /t:module One.cs

      執行之后,將生成名為One.netmodule文件;

      • 繼續執行,將多個模塊打包為程序集

      ?csc /t:library /addmodule:One.netmodule Two.cs

      執行之后,將生成名為Two.dll文件;

      • 最后,編譯Main函數和Two.dll為可執行文件

      ?csc /out:Anytao.Insidenet.MetatdataIL.exe /t:exe /r:Two.dll /r:mscorlib.dll Program.cs

      最終將得到本文開始時所加載的用于反編譯的程序集文件Anytao.Insidenet.MetadataIL.exe,在該執行命令中對幾個指示符開關做點說明:

      • /out:Anytao.Insidenet.MetadataIL.exe,表示輸出的可執行文件,及其名稱
      • /t:exe,表示輸出的文件類型為CUI(控制臺界面程序)程序;而/t:winexe,表示輸出為GUI(圖形界面程序)程序
      • /r:Two.dll,表示引用剛剛生產的Two.dll程序集
      • /r:mscorlib.dll,表示因為外部程序集mscorlib.dll,因為我們的程序中使用了Console靜態方法,而該方法則被定義在mscorlib.dll中。mscorlib.dll是如此的重要,我們將在本文之后的某些時候再次與mscorlib.dll握手,那時在對其進行一個詳細的分析,敬請期待。

      在cmd中的執行過程可以參考:

      通過分步執行的方式我們對csc編譯器的執行過程有個基本的了解,也同時從側面認識了每次在Visual Studio中執行“Build“或者“ReBuild”的縮影。綜上分析,我們可以簡單的看到:

      ?

      Note:在Visual Studio中,編譯是分模塊進行的,編譯結果保存在obj目錄中,最后再合并為可執行文件于bin目錄,同時默認情況下,編譯過程是增量式的,僅編譯發生修改的模塊,我將在后文給出較為詳細的過程。

      同時,我們還可以收獲以下幾個基本的結論:

      • cs代碼編譯之后將生成元數據和IL,并組成托管模塊(Module)的基本單元。

      • 多個托管模塊組成程序集,其實還包括一定的資源文件,只是沒有在此體現。

      • 程序集或者可執行文件是邏輯組織的基本單元,符合基本的Windows PE文件格式,可以被x86或者x64Windows直接加載執行。

      3 繼續深入

      一個或者多個模塊,再加上資源文件就形成了程序集(Assembly),作為邏輯組織的基本單元,

      事實上,此圖僅僅從粗粒度對程序集的基本組成有個大致的了解,實際上程序集中包含了復雜的結構和要素,例如PE Signature、Managed Resources、Strong Name Signature Hash,而其中最核心的要素則體現在上圖。

      • 程序集清單(MANIFEST)包含了程序集的自描述信息,主要包含AssemblyDef、FileDef、ManifestResourceDef和ExportedTypeDef,在反編譯選項中MANIFEST包含了詳細的內容。在《你必須知道的.NET》3.1節 “從Hello,world開始認識IL”對其有過詳細的描述,此不贅述。
      • PE文件頭,標準Windows PE頭文件(PE32或PE32+),PE文件的基本信息,例如文件類型,創建時間,本地CPU信息等。
      • CLR頭,包含CLR版本、模塊元數據、資源等信息。
      • 資源文件。

      執行View/Statisctics菜單,可以打開相關的統計信息:

      ?File?size????????????:?5632
      ?PE?header?size???????:?512?(496?used)????(?9.09%)
      ?PE?additional?info???:?1691??????????????(30.02%)
      ?Num.of?PE?sections???:?3
      ?CLR?header?size?????:?72?????????????????(?1.28%)
      ?CLR?meta-data?size??:?2212???????????????(39.28%)
      ?CLR?additional?info?:?0??????????????????(?0.00%)
      ?CLR?method?headers??:?52?????????????????(?0.92%)
      ?Managed?code?????????:?287???????????????(?5.10%)
      ?Data?????????????????:?2048??????????????(36.36%)
      ?Unaccounted??????????:?-1242?????????????(-22.05%)

      ?Num.of?PE?sections???:?3
      ???.text????-?3072
      ???.rsrc????-?1536
      ???.reloc???-?512

      ?CLR?meta-data?size??:?2212
      ???Module????????-????1?(10?bytes)
      ???TypeDef???????-????4?(56?bytes)??????0?interfaces,?0?explicit?layout
      ???TypeRef???????-???25?(150?bytes)
      ???MethodDef?????-????8?(112?bytes)?????0?abstract,?0?native,?8?bodies
      ???FieldDef??????-????1?(6?bytes)???????0?constant
      ???MemberRef?????-???29?(174?bytes)
      ???ParamDef??????-????2?(12?bytes)
      ???CustomAttribute-???16?(96?bytes)
      ???StandAloneSig?-????4?(8?bytes)
      ???PropertyMap???-????1?(4?bytes)
      ???Property??????-????1?(6?bytes)
      ???MethodSemantic-????2?(12?bytes)
      ???Assembly??????-????1?(22?bytes)
      ???AssemblyRef???-????1?(20?bytes)
      ???Strings???????-???920?bytes
      ???Blobs?????????-???328?bytes
      ???UserStrings???-????68?bytes
      ???Guids?????????-????16?bytes
      ???Uncategorized?-???192?bytes

      ?CLR?method?headers?:?52
      ???Num.of?method?bodies??-?8
      ???Num.of?fat?headers????-?4
      ???Num.of?tiny?headers???-?4

      ?Managed?code?:?287
      ???Ave?method?size?-?35

      ?我們將在后篇《深入程序集和模塊》中對PE頭,CLR頭和資源文件進行詳細論述。

      • IL代碼被組織為

      ????.class?public?auto?ansi?beforefieldinit?Anytao.Insidenet.MetadataIL.Two
      ???????extends?[mscorlib]System.Object
      ????{
      ??????.method?public?hidebysig?instance?string?
      ??????????????SayHello()?cil?managed
      ??????{
      ????????//?Code?size???????11?(0xb)
      ????????.maxstack??1
      ????????.locals?init?([0]?string?CS$1$0000)
      ????????IL_0000:??nop
      ????????IL_0001:??ldstr??????"Hello,?world."
      ????????IL_0006:??stloc.0
      ????????IL_0007:??br.s???????IL_0009

      ????????IL_0009:??ldloc.0
      ????????IL_000a:??ret
      ??????}?//?end?of?method?Two::SayHello

      ??????.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?Two::.ctor

      ????}?//?end?of?class?Anytao.Insidenet.MetadataIL.Two

      包裝在類似于匯編模樣的外衣下,我看依稀可見class, System.Object, method, public, string這些面向對象高級語言中的熟悉面孔,不同的只是多了很多benforefieldinit(參考:[你必須知道的.NET]第二十三回:品味細節,深入.NET的類型構造器), ret, maxstack, ldstr, stloc這些陌生的指令。然而IL并非一個怪胎,而正是基于其本身面向對象的匯編式風格,才造就了IL代碼成為名副其實的“中間語言”的重任。通過IL代碼,CLR就可在編譯時由JIT編譯轉換為Native Code,我們將在下節繼續分析這個過程的來龍去脈。

      欲知后事如何,且聽下文繼續:-)
      • 元數據是什么?
      • IL是什么?
      • 元數據和IL在JIT編譯時
      創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

      總結

      以上是生活随笔為你收集整理的[你必须知道的.NET]第二十四回:认识元数据和IL(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

      如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。