.NET IL

这一个是同济大学-2019 .NET 程序设计的作业。

我们编写一个 Program.cs

using System;
namespace course_05
{
// the function be applied to int
delegate void FuncInt(int var);
class Program
{
private int privateInt;
public int publicInt;
private static Program instance;
event EventHandler<FileFoundArgs> e;
static Program()
{
instance = null;
}
public Program()
{
// initialize eventhandler
// the <> argument is the second on
EventHandler<FileFoundArgs> onProgress = (sender, eventArgs) =>
Console.WriteLine("hello {0}", eventArgs.FoundFile);
e += onProgress;
}
public static Program Instance
{
get
{
Console.WriteLine("Hello Get");
return instance;
}
set
{
throw new Exception("You cannot write");
}
}
public void invokeHandler()
{
e?.Invoke(this, new FileFoundArgs("nmsl"));
}
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Program p = new Program();
Program ins = Program.Instance;
}
}
}

同时添加一个 FileFoundArgs.cs

namespace course_05
{
public class FileFoundArgs
{
public string FoundFile { get; }
public bool CancelRequested { get; set; }
public FileFoundArgs(string fileName)
{
FoundFile = fileName;
}
}
}

编译并获得 IL

csc Program.cs FileFoundArgs.cs
monodis Program.exe

下面分析 IL

IL Structure

在 IL 的最上部,可以看到一些基本的信息:

.assembly extern mscorlib
{
.ver 4:0:0:0
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
}
.assembly 'Program'
{
.custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::'.ctor'(int32) = (01 00 08 00 00 00 00 00 ) // ........
.custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() = (
01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.custom instance void class [mscorlib]System.Diagnostics.DebuggableAttribute::'.ctor'(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (01 00 07 01 00 00 00 00 ) // ........
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module Program.exe // GUID = {F3656A1D-A631-49DB-AF34-8A7B3333C029}

程序集

.assembly extern mscorlib
{
.ver 4:0:0:0
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
}

这里指定了我们使用的 mscorlib 程序集,IL 中已经有对象和 .NET Framework

下面的几行分别给出的是程序集模块的名称

.assembly 'Program'
{
.custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::'.ctor'(int32) = (01 00 08 00 00 00 00 00 ) // ........
.custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() = (
01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.custom instance void class [mscorlib]System.Diagnostics.DebuggableAttribute::'.ctor'(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (01 00 07 01 00 00 00 00 ) // ........
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module Program.exe // GUID = {F3656A1D-A631-49DB-AF34-8A7B3333C029}

Class Program

.namespace course_05
{
.class private auto ansi Program
extends [mscorlib]System.Object
{
...

可以看到,namespace 仍然有这种包含的定义,但是这里是分离式的了,同一个 namespace 的 FuncInt 和它在在 IL 中的地址似乎没有什么联系。

extends [mscorlib]System.Object

这里指定了它的 BaseClass。

数据成员

.class private auto ansi Program
extends [mscorlib]System.Object
{
.field private int32 privateInt
.field public int32 publicInt
.field private static class course_05.Program 'instance'
.field private class [mscorlib]System.EventHandler`1<class course_05.FileFoundArgs> e
.custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::'.ctor'() = (01 00 00 00 ) // ....
.custom instance void class [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::'.ctor'(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (01 00 00 00 00 00 00 00 ) // ........

可以看到

.field

The field directive indicates a new defined field which is state information for a class. Here, the syntax as shown below:

.field attributes type fieldname

In the C# code, we can define an integer type field as the following:

> .field private initonly int32 x
> .field private initonly int32 y
>

字段被声明为 .field, 实际这里是不会有内存被申请的

private public static 等都有多个层次的标注

程序入口

// method line 12
.method private static hidebysig
default void Main (string[] args) cil managed
{
// Method begins at RVA 0x2158
.entrypoint
// Code size 25 (0x19)
.maxstack 1
.locals init (
class course_05.Program V_0,
class course_05.Program V_1)
IL_0000: nop
IL_0001: ldstr "Hello World!"
IL_0006: call void class [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: newobj instance void class course_05.Program::'.ctor'()
IL_0011: stloc.0
IL_0012: call class course_05.Program class course_05.Program::get_Instance()
IL_0017: stloc.1
IL_0018: ret
} // end of method Program::Main

可以看到 main 提供了 cil managed 和 .entrypoint,后者表示是程序的入口。

其余是 IL 对 stack 等空间的操作了

属性

.method public static hidebysig specialname
default class course_05.Program get_Instance () cil managed
{
// Method begins at RVA 0x2108
// Code size 22 (0x16)
.maxstack 1
.locals init (
class course_05.Program V_0)
IL_0000: nop
IL_0001: ldstr "Hello Get"
IL_0006: call void class [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldsfld class course_05.Program course_05.Program::'instance'
IL_0011: stloc.0
IL_0012: br.s IL_0014
IL_0014: ldloc.0
IL_0015: ret
} // end of method Program::get_Instance
// method line 10
.method public static hidebysig specialname
default void set_Instance (class course_05.Program 'value') cil managed
{
// Method begins at RVA 0x212a
// Code size 12 (0xc)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "You cannot write"
IL_0006: newobj instance void class [mscorlib]System.Exception::'.ctor'(string)
IL_000b: throw
} // end of method Program::set_Instance

可以看到

.field private static class course_05.Program 'instance'

这有个 instance 字段声明的操作,同时编译器生成了 get_set_.

Event

.field private class [mscorlib]System.EventHandler`1<class course_05.FileFoundArgs> e

Event 和 字段成员一样处理

Method

// method line 11
.method public hidebysig
instance default void invokeHandler () cil managed
{
// Method begins at RVA 0x2137
// Code size 31 (0x1f)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.EventHandler`1<class course_05.FileFoundArgs> course_05.Program::e
IL_0007: dup
IL_0008: brtrue.s IL_000d
IL_000a: pop
IL_000b: br.s IL_001e
IL_000d: ldarg.0
IL_000e: ldstr "nmsl"
IL_0013: newobj instance void class course_05.FileFoundArgs::'.ctor'(string)
IL_0018: callvirt instance void class [mscorlib]System.EventHandler`1<class course_05.FileFoundArgs>::Invoke(object, !0)
IL_001d: nop
IL_001e: ret
} // end of method Program::invokeHandler

可以看看 invokeHandler 的 method,在 stack 里面制定了 maxstack ,一些 stack 上的变量在 IL 开头的时候先行 ld:

IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.EventHandler`1<class course_05.FileFoundArgs> course_05.Program::e
IL_0007: dup

这里把多个参数变量压入 stack

IL_001e: ret

这里返回

Delegate

对于 Delegate ,有如下定义:

.namespace course_05
{
.class private auto ansi sealed FuncInt
extends [mscorlib]System.MulticastDelegate
{
// method line 1
.method public hidebysig specialname rtspecialname
instance default void '.ctor' (object 'object', native int 'method') runtime managed
{
// Method begins at RVA 0x0
// Disassembly of native methods is not supported
} // end of method FuncInt::.ctor
// method line 2
.method public virtual hidebysig newslot
instance default void Invoke (int32 var) runtime managed
{
// Method begins at RVA 0x0
// Disassembly of native methods is not supported
} // end of method FuncInt::Invoke
// method line 3
.method public virtual hidebysig newslot
instance default class [mscorlib]System.IAsyncResult BeginInvoke (int32 var, class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed
{
// Method begins at RVA 0x0
// Disassembly of native methods is not supported
} // end of method FuncInt::BeginInvoke
// method line 4
.method public virtual hidebysig newslot
instance default void EndInvoke (class [mscorlib]System.IAsyncResult result) runtime managed
{
// Method begins at RVA 0x0
// Disassembly of native methods is not supported
} // end of method FuncInt::EndInvoke
} // end of class course_05.FuncInt
}

可以看到,这里实际上是对 event 的一个封装,提供了 Call 等途径和对应的类型。

References