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标记用来表示我们所引用的外部程序集,比如我们添加一个新的引用时: