.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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...