[Programming IL]创建一个类,How To Declare A Class
引言
在.Net平台中,面向对象是一个非常重要的概念,那么在IL是怎样对面向对象进行支持的呢? 让我们从创建一个类开始
例子
1: .assembly extern mscorlib {}
2: .assembly MyClass {}
3: .class public auto unicode XWang extends [mscorlib]System.Object
4: {
5: .method public hidebysig specialname rtspecialname instance void .ctor() il managed
6: {
7: call instance void [mscorlib]System.Object::.ctor()
8: ret
9: }
10:
11: .method public hidebysig static void main() cil managed
12: {
13: .entrypoint
14: ldstr "Welcome to Intermediate Language"
15: call void [mscorlib]System.Console::WriteLine(class System.String)
16: ret
17: }
18: }
该程序从创建一个类开始,使用了构造函数并输出了一行字符串
有几个指令需要说明一下
.class 声明一个类
.method 声明方法
specialname 对于方法的特殊处理, 比如声明一个属性编译成IL也会有specialname标识
rtspecialname: 一个只用于.Net内部的标识,使用于四种情况
1. 实例构造函数 2. 类构造函数 3. _VtblGap* 声明方法表 4. _Deleted 声明不使用但是没有从元数据中删除的方法
来个复杂点的. :)
从C#开始
1: using System;
2: using System.Collections.Generic;
3:
4: namespace Roger.Testing
5: {
6: public class Testing
7: {
8: private int m_private;
9: private int m_init = 2;
10:
11: public static void Main()
12: {
13: }
14:
15: static Testing()
16: {
17: // DO Something
18: int i = 2;
19: }
20:
21: public void DoSth()
22: {
23: for(int i =0; i< m_init; i++)
24: {
25: m_private += i;
26: if(m_private > 1) m_private = 1;
27: }
28: }
29:
30: public void While()
31: {
32: while(m_init > 0) m_init--;
33:
34: do
35: {
36: m_init++;
37: }while(m_init < 10);
38: }
39:
40: public void TestSwitch()
41: {
42: switch(m_init)
43: {
44: case 0:
45: m_private = 1;
46: break;
47: case 1:
48: m_private = 2;
49: break;
50: case 2:
51: m_private = 3;
52: break;
53: default:
54: m_private = 100;
55: break;
56: }
57: }
58: }
59: }
那一个类的字段是如何定义的,方法是如何声明,流程如何控制的呢,我们从代码编译生成的方法列表图上面开始吧
1. 字段的声明
.field private int32 m_init
2. 字段的初始化
1: .method public hidebysig specialname rtspecialname
2: instance void .ctor() cil managed
3: {
4: // Code size 14 (0xe)
5: .maxstack 8
6: IL_0000: ldarg.0
7: IL_0001: ldc.i4.2
8: IL_0002: stfld int32 Roger.Testing.Testing::m_init
9: IL_0007: ldarg.0
10: IL_0008: call instance void [mscorlib]System.Object::.ctor()
11: IL_000d: ret
12: } // end of method Testing::.ctor
13:
IL会为该类生成一个实例构造函数而后调用Object的构造函数并初始化那些数据
3. 类构造函数
method .cctor
4. IF - ELSE 判断, For循环
1: .method public hidebysig instance void DoSth() cil managed
2: {
3: // Code size 48 (0x30)
4: .maxstack 3
5: .locals init (int32 V_0)
6: IL_0000: ldc.i4.0
7: IL_0001: stloc.0
8: IL_0002: br.s IL_0026
9: IL_0004: ldarg.0
10: IL_0005: dup
11: IL_0006: ldfld int32 Roger.Testing.Testing::m_private
12: IL_000b: ldloc.0
13: IL_000c: add
14: IL_000d: stfld int32 Roger.Testing.Testing::m_private
15: IL_0012: ldarg.0
16: IL_0013: ldfld int32 Roger.Testing.Testing::m_private
17: IL_0018: ldc.i4.1
18: IL_0019: ble.s IL_0022
19: IL_001b: ldarg.0
20: IL_001c: ldc.i4.1
21: IL_001d: stfld int32 Roger.Testing.Testing::m_private
22: IL_0022: ldloc.0
23: IL_0023: ldc.i4.1
24: IL_0024: add
25: IL_0025: stloc.0
26: IL_0026: ldloc.0
27: IL_0027: ldarg.0
28: IL_0028: ldfld int32 Roger.Testing.Testing::m_init
29: IL_002d: blt.s IL_0004
30: IL_002f: ret
31: } // end of method Testing::DoSth
32:
ldc.i4 加载int4(32)
br.s = br + s, br 为branch意值分支, s为short parameter
dup = duplicate, 拷贝栈顶的数据值,如果没有栈顶,则会抛出异常
ldfld = load field 加载某个字段的值
stfld = save field 保存字段的值
ble = branch if less or equal, 小于等于的分支
ble.s = short parameter的ble
blt = branch if less
5. While, Do-While
1: .method public hidebysig instance void While() cil managed
2: {
3: // Code size 50 (0x32)
4: .maxstack 8
5: IL_0000: br.s IL_0010
6: IL_0002: ldarg.0
7: IL_0003: dup
8: IL_0004: ldfld int32 Roger.Testing.Testing::m_init
9: IL_0009: ldc.i4.1
10: IL_000a: sub
11: IL_000b: stfld int32 Roger.Testing.Testing::m_init
12: IL_0010: ldarg.0
13: IL_0011: ldfld int32 Roger.Testing.Testing::m_init
14: IL_0016: ldc.i4.0
15: IL_0017: bgt.s IL_0002
16: IL_0019: ldarg.0
17: IL_001a: dup
18: IL_001b: ldfld int32 Roger.Testing.Testing::m_init
19: IL_0020: ldc.i4.1
20: IL_0021: add
21: IL_0022: stfld int32 Roger.Testing.Testing::m_init
22: IL_0027: ldarg.0
23: IL_0028: ldfld int32 Roger.Testing.Testing::m_init
24: IL_002d: ldc.i4.s 10
25: IL_002f: blt.s IL_0019
26: IL_0031: ret
27: } // end of method Testing::While
28:
6. Switch
1: .method public hidebysig instance void TestSwitch() cil managed
2: {
3: // Code size 60 (0x3c)
4: .maxstack 2
5: .locals init (int32 V_0)
6: IL_0000: ldarg.0
7: IL_0001: ldfld int32 Roger.Testing.Testing::m_init
8: IL_0006: stloc.0
9: IL_0007: ldloc.0
10: IL_0008: switch (
11: IL_001b,
12: IL_0023,
13: IL_002b)
14: IL_0019: br.s IL_0033
15: IL_001b: ldarg.0
16: IL_001c: ldc.i4.1
17: IL_001d: stfld int32 Roger.Testing.Testing::m_private
18: IL_0022: ret
19: IL_0023: ldarg.0
20: IL_0024: ldc.i4.2
21: IL_0025: stfld int32 Roger.Testing.Testing::m_private
22: IL_002a: ret
23: IL_002b: ldarg.0
24: IL_002c: ldc.i4.3
25: IL_002d: stfld int32 Roger.Testing.Testing::m_private
26: IL_0032: ret
27: IL_0033: ldarg.0
28: IL_0034: ldc.i4.s 100
29: IL_0036: stfld int32 Roger.Testing.Testing::m_private
30: IL_003b: ret
31: } // end of method Testing::TestSwitch
32:
While 和 Do-While 和Switch都用到了Label的特性,利用Label进行跳转
参考:
Expert .Net 2.0 Assembler