CIL和动态程序集的作用

时间:2021-12-29 07:13:31

CIL是一种底层语言,CIL语言仅仅定义了一组通用的关键字,由CIL编译器进一步将这些关键字分为指令,特性以及操作码。指令是指用来描述程序集总体结构的CIL关键字,指令在语法上使用一个“.”做前缀来表示,,特性是指定以何种方式执行指令的CIL关键字,比如.public,操作码就是实现程序集实现逻辑。CIL是一个以栈为基础的开发语言,在CIL中实现栈的是虚拟执行栈,因为这种的数据访问方式,导致CIL不能直接访问一个数据,必须先显示加载入栈中,在需要使用该值的时候,再使用一系列的操作码,将数值从栈中存储到内存中,例如:public void PrintMessage()

{

string myMessage=""Hello.";

Console.WriteLine(myMessage);

}

通过C#编译器将这个方法翻译为CIL代码:

.method public hidebysig instance void PrintMessage() cil managed

{

.maxstack 1 //虚拟栈的长度,可自定义,默认为8,此处为自定义

.locals init([0] string maMessage) //定义一个本地字符串变量(在索引0处)

.ldstr "Hello." //加载字符串到虚拟栈

.stloc.0 //存储字符串到本地变量

.ldloc.0 //调用索引0处的值

.call void[mscorlib]System.Console::WriteLine(string) //使用当前的值调用方法

.ret

}

这一开发语言作用就在于可以在只有bll文件的情况下直接修改源代码,当然这需要有一定的CIL知识,这叫做正反向工程,首先我们写一个简单的控制台应用程序:

using System;
namespace HelloProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello CIL code!");
            Console.ReadLine();
        }
    }
}

先使用编译器或者csc.exe将文件编译为exe文件,之后是vs开发人员命令提示中使用ildasm.exe打开exe文件,进行转储为il文件或者使用 “ildasm /?”进行查看命令,根据命令直接转储il文件,以下是转储的结果,我对一些注释进行了删除,已方便看起来更简洁:

//引用的程序集
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                 
  .ver 4:0:0:0
}

//我的程序集
.assembly  HelloProgram
{
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
.module HelloProgram.exe
// MVID: {F2A7E657-9431-4A33-BF31-C8C1898B8A22}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00020003    //  ILONLY 32BITPREFERRED
// Image base: 0x002F0000


// =============== CLASS MEMBERS DECLARATION ===================

.class  private auto ansi beforefieldinit HelloProgram.Program
       extends [mscorlib]System.Object
{
  .method private hidebysig static
          void  Main(string[] args) cil managed
  // SIG: 00 01 01 1D 0E
  {
    .entrypoint
    // 方法在 RVA 0x2050 处开始
    // 代码大小       19 (0x13)
    .maxstack  8
    .language ‘{3F5162F8-07C6-11D3-9053-00C04FA302A1}‘, ‘{994B45C4-E6E9-11D2-903F-00C04FA302A1}‘, ‘{5A869D0B-6611-11D3-BD2A-0000F80849BD}‘
// Source File ‘D:\HelloProgram\HelloProgram\Program.cs‘
    .line 9,9 : 9,10 ‘D:\\HelloProgram\\HelloProgram\\Program.cs‘
//000009:         {
    IL_0000:  nop
//000010:             Console.WriteLine("Hello CIL code!");
    IL_0001:  ldstr      "Hello CIL code!"
    IL_0006:   call       void [mscorlib]System.Console::WriteLine(string)
    IL_000b: nop
    .line 11,11 : 13,32 ‘‘
//000011:             Console.ReadLine();
    IL_000c: call  string [mscorlib]System.Console::ReadLine()
    IL_0011: pop
    .line 12,12 : 9,10 ‘‘
//000012:         }
    IL_0012:  ret
  } // end of method Program::Main

  .method  public hidebysig specialname rtspecialname
          instance void  .ctor() cil managed
  // SIG: 20 00 01
  {
    // 方法在 RVA 0x2064 处开始
    // 代码大小       8 (0x8)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  nop
    IL_0007:  ret
  } // end of method Program::.ctor

} // end of class HelloProgram.Program
如以上的cil代码注释所言,.assembly extern标记用来表示我们所引用的外部程序集,比如我们添加一个新的引用时: