.Net基礎——程式集與CIL

来源:https://www.cnblogs.com/freddysia/archive/2018/07/29/9314658.html
-Advertisement-
Play Games

1. 程式集和CIL: 程式集是由.NET語言的編譯器接受源代碼文件產生的輸出文件,通常分為 exe和dll兩類,其中exe包含Main入口方法可以雙擊執行,dll則需要被其他程式集調用執行。 CIL(Common Intermediate Language): 公共中間語言①,需要被編譯成二進位機 ...


1. 程式集和CIL:

  • 程式集是由.NET語言的編譯器接受源代碼文件產生的輸出文件,通常分為 exe和dll兩類,其中exe包含Main入口方法可以雙擊執行,dll則需要被其他程式集調用執行。
  • CIL(Common Intermediate Language): 公共中間語言,需要被編譯成二進位機器碼之後才會被電腦執行。

2. 程式集包含:

  • 程式的CIL
  • 程式中使用的類型的元數據(metadata)
  • 程式集清單
  • 一些資源集

程式被編譯成程式集(exe為例)之後,雙擊運行,程式集會被載入入CLR,CLR執行下麵的步驟:
  1.檢查程式集的安全特性。
  2.進行記憶體分配。
  3.把程式集中的可執行代碼發送給JIT(Just-in-Time)編譯器,把其中的一部分代碼編譯成為本機代碼。
其中,JIT只會編譯被調用的部分CIL代碼,並把編譯的結果緩存起來,以備在後面的程式中的多次調用。這保證了編譯與運行的效率。

經過JIT編譯之後的代碼即是本機代碼,本機代碼最終被CPU執行。


我們通過一段簡單的代碼來加深理解:

 1. 打開VS,用C#編寫一段如下程式:

using System;

namespace ILTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello Fred");
            Console.Read();
        }
    }
}

 

 2. 使用 ILASM 工具將程式集反編譯為IL(也可生成為ILTest.txt,尾碼名不影響文本文件內容):

ildasm ILTest.exe /output:ILTest.IL

生成文本文件如下:

 1 //  Microsoft (R) .NET Framework IL Disassembler.  Version 4.6.1055.0
 2 
 3 // Metadata version: v4.0.30319
 4 .assembly extern mscorlib
 5 {
 6   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
 7   .ver 4:0:0:0
 8 }
 9 .assembly ILTest
10 {
11   .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
12   .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
13                                                                                                              63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
14 
15   // --- 下列自定義特性會自動添加,不要取消註釋 -------
16   //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) 
17 
18   .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 06 49 4C 54 65 73 74 00 00 )                // ...ILTest..
19   .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
20   .custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
21   .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
22   .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 06 49 4C 54 65 73 74 00 00 )                // ...ILTest..
23   .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20   // ...Copyright .. 
24                                                                                                   20 32 30 31 38 00 00 )                            //  2018..
25   .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
26   .custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 ) 
27   .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 38 34 66 35 62 34 30 65 2D 39 31 61 65   // ..$84f5b40e-91ae
28                                                                                                   2D 34 62 66 63 2D 61 62 38 39 2D 34 61 30 66 66   // -4bfc-ab89-4a0ff
29                                                                                                   66 36 64 30 38 31 61 00 00 )                      // f6d081a..
30   .custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 )             // ...1.0.0.0..
31   .custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1C 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B   // ....NETFramework
32                                                                                                         2C 56 65 72 73 69 6F 6E 3D 76 34 2E 36 2E 31 01   // ,Version=v4.6.1.
33                                                                                                         00 54 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73   // .T..FrameworkDis
34                                                                                                         70 6C 61 79 4E 61 6D 65 14 2E 4E 45 54 20 46 72   // playName..NET Fr
35                                                                                                         61 6D 65 77 6F 72 6B 20 34 2E 36 2E 31 )          // amework 4.6.1
36   .hash algorithm 0x00008004
37   .ver 1:0:0:0
38 }
39 .module ILTest.exe
40 // MVID: {90543B0E-D1B4-4FFF-9260-57E27FBC4F8B}
41 .imagebase 0x00400000
42 .file alignment 0x00000200
43 .stackreserve 0x00100000
44 .subsystem 0x0003       // WINDOWS_CUI
45 .corflags 0x00020003    //  ILONLY 32BITPREFERRED
46 // Image base: 0x00960000
47 
48 
49 // =============== CLASS MEMBERS DECLARATION ===================
50 
51 .class public auto ansi beforefieldinit ILTest.Program
52        extends [mscorlib]System.Object
53 {
54   .method public hidebysig static void  Main(string[] args) cil managed
55   {
56     .entrypoint
57     // 代碼大小       19 (0x13)
58     .maxstack  8
59     IL_0000:  nop
60     IL_0001:  ldstr      "Hello Fred"
61     IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
62     IL_000b:  nop
63     IL_000c:  call       int32 [mscorlib]System.Console::Read()
64     IL_0011:  pop
65     IL_0012:  ret
66   } // end of method Program::Main
67 
68   .method public hidebysig specialname rtspecialname 
69           instance void  .ctor() cil managed
70   {
71     // 代碼大小       8 (0x8)
72     .maxstack  8
73     IL_0000:  ldarg.0
74     IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
75     IL_0006:  nop
76     IL_0007:  ret
77   } // end of method Program::.ctor
78 
79 } // end of class ILTest.Program
80 
81 
82 // 
View Code

其中包含了程式的元數據,程式集清單和一些其他資源信息。

它們描述並組成了這段程式的類型信息,安全信息,版本信息以及對其它程式集的引用信息等,使得程式集擁有了自我描述的特性。其中,元數據是反射得以實現的重要條件。

 除此之外還包含了IL代碼,IL是經過編譯器(這裡是csc)編譯產生的中間語言代碼。

 

我們可以通過修改IL代碼來控製程序的執行:

打開生成的文本文件,將Main方法中的輸出字元串修改為"Hello Tommy":

 

使用ILASM工具將IL文件重新編譯成ILTest2.exe:

 

雙擊運行exe結果如下:

 

 

也許你會覺得納悶,為什麼要把源代碼先翻譯成CIL再翻譯成本機代碼,而不是一步到位呢??

當程式被編譯成程式集之後就脫離了語言的限制,.NET平臺下的語言通過程式集的調用突破了語言的阻礙。

例如C#程式可以調用VB生成的程式集,將語言的特殊性轉換成了CIL這一通用且規範的概念,好比全國各個地方的人講著不同的方言,彼此之間難以溝通,但是先講方言翻譯成了CIL之一普通話,從此便消除了語言的障礙。

除此之外,如果直接從高級語言編譯成機器語言,不同廠商生成的CPU讀取不同的指令,如果有x門高級語言,有y種讀取不同指令集的CPU,那麼需要有x*y種編譯器去將不同的語言與CPU指令一一匹配。

有了CIL之後,我們只需x種編譯器將高級語言轉換成CIL,再經過y種編譯器將CIL轉換成二進位指令。 一共僅需要x+y種不同的編譯器。

 

 

原創文章,未經允許禁止轉載。


 

註:①公共中間語言在一些地方也被叫做MSIL(Microsoft Intermediate Language)或IL(Intermediate Language)。本文中的CIL,IL,MSIL指的都是公共中間語言這一概念。

  ②ILASM和ILDASM工具詳見:here


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Chrome開發者工具中Network功能介紹 第一列Name:請求的名稱,一般會將URL的最後一 部分內容當作名稱。 第二列Status: 響應的狀態碼,這裡顯示為200,代表響應是正常的。通過狀態碼,我們可 以判斷發送了請求之後是否得到了正常的響應。 第三列Type: 請求的文檔類型。這裡為do ...
  • 一、線性表的定義 線性表是n(n>=0)個具有相同特性的數據元素的有限序列。 線性表是最簡單、最常用的一種數據結構 線性表屬於線性結構的一種 如果一個數據元素序列滿足: (1)除第一個和最後一個數據元素外,每個數據元素只有一個前驅數據元素和一個後繼數據元素; (2)第一個數據元素沒有前驅數據元素; ...
  • 題意 給出三個已經排好序的數組$a, b, c$ 在$100$次詢問內找出第$k$小的元素 Sol 一種很顯然的$log^2n$的做法:首先在$a$中二分,然後再$b,c$中二分。這樣可以得到$60$分的好成績。 然而這演算法就沒什麼優化的空間了。。。 考慮另一種做法。 我們每次對三個數組詢問第$\f ...
  • 有時候,可能會有一些類似這樣的需求,具體如圖所見,取首字母。 ...
  • 前言 Spring框架為什麼如此流行? 原來Spring框架解決了一個很關鍵的問題,它可以把對象之間的依賴關係轉為用配置文件來管理,也就是它的依賴註入機制。IOC容器用來管理這些Bean,管理Bean的關係以及生命周期,然而這與之前將應用程式主動new對象不同,Spring實現使用IOC容器創建對象 ...
  • 接著 上篇 目前也算是交代清楚了相關的類。那麼框架具體是如何來實例化的呢?整個的流程是怎麼樣的。 我們參考源碼中的Test文件夾來看看: var collection = new ServiceCollection(); collection.AddTransient<DependOnNonexis ...
  • 本文主要以一個簡單的小例子,描述C# Winform程式異常關閉時,如何進行捕獲,並記錄日誌。 ...
  • 誤解一:併發就是多線程 實際上多線程只是併發編程的一種形式,在C 中還有很多更實用、更方便的併發編程技術,包括非同步編程、並行編程、TPL 數據流、響應式編程等。 誤解二:只有大型伺服器程式才需要考慮併發 伺服器端的大型程式要響應大量客戶端的數據請求,當然要充分考慮併發。但是桌面程式和手機、平板等移動 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...