MSIL探索-IL介绍
by zguosir/gshzheng
1.
我们用C#,Vb.Net,Asp.Net或其它的与.Net兼容的语言写的代码最终都会编译成IL。如,我们用Cobol写的程序,可以在C#中修改,然后在Asp.Net中使用。因此,理解IL是我们理解.Net相关技术的最好的方式。
假设您已经至少熟悉一种.Net语言,让我们一步一步揭开IL的面纱,
a1.il
.assembly
zzz{}
.method
static void mymethod()
{
.entrypoint
ldstr “Hello”
call
void [mscorlib]System.Console::WriteLine(string)
ret
}
Output
hello
这是比较简单的IL程序,必须指定伪指令.assembly .entrypoint,以及ret函数结束指令。(注,译者还很老土,用的环境Net1.1,Net2.0会很不一样,但我们没必要在版本上做更多的计较)
以.开始的语句,我们称之伪指令(derective),如创建一类或方法的指令;
不以.开始的语句,是真正的汇编指令。
在IL中,首先被执行的第一个函数为入口函数(entrypoint function),一个程序只能有一个入口函数,.entrypoint是伪指令,它的位置可以放在函数开始处,也可以放在函数的结束处。
ret指令表示函数代码的结束,不能省略。
call语句是函数调用指令,指令的调用有如下的细节
l 返回值(void)
l 引用的外部装配件([mscorlib])
l 命名空间(System)
l 类(Console)
l 方法名称(WriteLine)
l 方法参数类型(string)
2.
下面是一个稍微复杂一点IL程序,其中引入了类的定义
a2.il
.assembly
zzz{}
.class
private auto ansi zzz extends [mscorlib]System.Object
{
.method
public hidebysig static void mymethod() il managed
{
.entrypoint
ldstr
"Hello"
call
void [mscorlib]System.Console::WriteLine(string)
ret
}
}
OutPut
Hello
伪指令.class定义了一个类,并且有三个修饰词
l private: 表示对类的程序的访问只能限制在当前类内部。
l auto: 表示类在内存中的存储只有在运行时才能决定。
l ansi: 原代码可以被分割为两部分,受控的和非受控的。
l il managed: 暂不说明。
伪指令.method的修饰词
l public: 方法的访问级别。
l hidebysig: 此属性让父类的这个方法对派生类来说是隐藏的。
l static: 静态的方法是属于类而不是属于对象的。标记为entrypoint的方法首先是static的。
3.
下面一个再复杂一点的程序,填加了更多的伪指令,还有类的构造函数的写法
a3.il
.module
a3.exe
.subsystem
3
.corflags
1
.assembly
extern mscorlib
{
.publickeytoken = (B7
.ver 1:0:5000:0
}
.assembly
a3
{
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.class
private auto ansi zzz extends [mscorlib]System.Object
{
.method
public hidebysig static void mymethod() il managed
{
.entrypoint
ldstr
"Hello"
call
void [mscorlib]System.Console::WriteLine(class [mscorlib]System.String)
ret
}
.method
public hidebysig specialname rtspecialname instance void .ctor() il managed
{
.maxstack
8
ldstr
"Hello1"
call
void [mscorlib]System.Console::WriteLine(class [mscorlib]System.String)
ldarg.0
call
instance void [mscorlib]System.Object::.ctor()
ret
}
}
Output
Hello
.ctor: ctor就是constructor
rtspecialname: 这个属性告诉运行时(runtime)当前函数有个特殊的名字,应该进行某些特殊的对待。
Specialname: 这是通知编译器,当前函数是特殊的,RT可能忽略这个属性。
Instance: 指明函数调用是一个相对于实例的调用。
ldarg.0 一般是取的在执行堆栈上的this指针或第0个参数的地址(对于静态方法)。
.maxstack:指定当方法被执行时,在stack上的最大元素数
.module:所有的IL文件必须是某个module的一部分,这里module的名字未必与exe的名字相同。
.subsystem: 这个伪指令用来指定程序将要在哪个OS上运行,它也是指定运行程序类型的一种方式。下面是值的含义:
2- Windows 控制台程序
3- WinForm程序
5- OS/2
.corflags: 1表示可执行程序,4表示类库
.assembly 我们创建的所有东西都是manifest的一部分,assembly伪指令是manifest的开始指令,manifest包括module,一个module只能包含一个assembly伪指令。如果exe程序,assembly只必须有的,而对于dll类库来说,它是可以缺省的。在assembly伪指令中,包含着其它的伪指令。
.hash: 指明assembly的hash代码。
.ver: 指明assembly的版本表示,它有4部分组成,有冒号分割,依次分别表示主版本号、次版本号、内建build号,修正号。
extern:如果需要引用其它的assemblies,就需要用到extern伪指令。
originator:这个伪指令揭示了dll创建着的唯一标识,它是创建者公钥(public key)的8位数字,显然是个hash code。
4.
现在,我们把一个最简单的c#程序,反编译成il后,再来看程序,就貌似不怎么陌生了。
a4.cs
public
class a4
{
public static void
{
System.Console.WriteLine("Hello");
}
}
>csc
a4.cs
>ildasm
a4.exe /out=a4.il
a4.il
// Microsoft (R) .NET Framework IL Disassembler. Version 1.1.4322.573
// Copyright (C) Microsoft Corporation
1998-2002. All rights reserved.
.assembly
extern mscorlib
{
.publickeytoken = (B7
.ver 1:0:5000:0
}
.assembly
a4
{
// --- 下列自定义属性会自动添加,不要取消注释 -------
//
.custom instance void
[mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(bool,
//
bool) = ( 01 00 00 01 00 00 )
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module
a4.exe
// MVID:
{6E8E5294
.imagebase
0x00400000
.subsystem
0x00000003
.file
alignment 512
.corflags
0x00000001
// Image
base: 0x00da0000
//
//
============== CLASS STRUCTURE DECLARATION ==================
//
.class
public auto ansi beforefieldinit a4
extends [mscorlib]System.Object
{
} // end
of class a4
//
=============================================================
//
=============== GLOBAL FIELDS AND METHODS ===================
//
=============================================================
//
=============== CLASS MEMBERS DECLARATION ===================
// note that class flags, 'extends' and
'implements' clauses
// are provided here for information
only
.class
public auto ansi beforefieldinit a4
extends [mscorlib]System.Object
{
.method public hidebysig static void
{
.entrypoint
// 代码大小 11 (0xb)
.maxstack
1
IL_0000:
ldstr "Hello"
IL_0005:
call void
[mscorlib]System.Console::WriteLine(string)
IL_
} // end of method a4::Main
.method public hidebysig specialname
rtspecialname
instance void .ctor() cil managed
{
// 代码大小 7 (0x7)
.maxstack
1
IL_0000:
ldarg.0
IL_0001:
call instance void
[mscorlib]System.Object::.ctor()
IL_0006:
ret
} // end of method a4::.ctor
} // end
of class a4
//
=============================================================
//***********
反汇编完成 ***********************
//
WARNING: Created Win32 resource file a4.res