MSIL Hello World

博客园地址

最近由于需要,开始阅读 MSIL 方面的东西。我读的是《.NET 探秘——MSIL 权威指南》(《Expert .NET 2.0 IL Assembler》中译版)。感觉没什么好说的,毕竟只要对 .NET 及其后面的东西了解一些,然后当做汇编来看,就好了。剩下的就是实践。

如书上所言,前面已经有人做出了这项研究了,如 Anders Liu、装配脑袋、Flier Lu。前辈们都是老手了,我也不好说什么,毕竟我刚刚入门。

这里就贴出昨晚写的一个 HelloWorld 程序吧。读了4天的收获。为了方便没学过 MSIL 的同志们,在上面都附上了实现同样功能的 C# 代码。

嗯,高级的东西还不敢说,要再仔细看,多练习才行啊。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
.assembly extern mscorlib { auto }
.assembly MyIlApp { }
.module MyIlApp.exe

.namespace MyIlApp
{
// public struct VC
.class public value sealed auto VC
{
// public int val_int32;
.field public int32 val_int32
// public string val_string;
.field public string val_string
}

// public sealed class MainClass
.class public sealed auto ansi MainClass
{

// public static int _val;
.field public static int32 _val

// public static void check(int argument1)
.method public static void check(int32) cil managed
{
// string temp;
.locals init ([0]string temp)

// if (MyIlApp.MainClass._val == argument1)
// {
// System.Console.WriteLine("The value equals to the argument.");
// }
// else
// {
// System.Console.WriteLine("The value does not equal to the argument.");
// }
ldsfld int32 MyIlApp.MainClass::_val
ldarg.0
beq TrueEqual
ldstr "The value does not equal to the argument."
call void [mscorlib]System.Console::WriteLine(string)
br ThisIsEnd
TrueEqual:
ldstr "The value equals to the argument."
call void [mscorlib]System.Console::WriteLine(string)

// temp = argument1.ToString(); // 注意这里用 call 而不是 callvirt,因为 argument1 是 int32 类型,未装箱的时候没有V表
ThisIsEnd:
ldarga.s 0
call instance string [mscorlib]System.Int32::ToString()
stloc.0

// System.Console.Write("The real value is:");
ldstr "The real value is: "
call void [mscorlib]System.Console::Write(string)

// System.Console.WriteLine(temp);
ldloc.0
call void [mscorlib]System.Console::WriteLine(string)

// return;
ret
}

// public static void Main()
.method public static void Main() cil managed
{
// .entrypoint 伪指令表示是程序入口点
.entrypoint

/* Test Case 1 */

// string input;
// int v;
.locals init ([0] string input,
[1] int32 v)

// System.Console.WriteLine("Hi. Please input a string:");
ldstr "Hi. Please input a string:"
call void [mscorlib]System.Console::WriteLine(string)

// input = System.Console.ReadLine();
call string [mscorlib]System.Console::ReadLine()
stloc.0

// System.Console.WriteLine(input);
ldloc.0
call void [mscorlib]System.Console::WriteLine(string)

// v = System.Int32.Parse(input);
ldloc.0
call int32 [mscorlib]System.Int32::Parse(string)
stloc.1

// MyIlApp.MainClass._val = 9000;
ldc.i4 9000
stsfld int32 MyIlApp.MainClass::_val

// System.Console.WriteLine(MyIlApp.MainClass._val.ToString());
ldsflda int32 MyIlApp.MainClass::_val
call instance string [mscorlib]System.Int32::ToString()
call void [mscorlib]System.Console::WriteLine(string)

// MyIlApp.MainClass.check(v);
ldloc.1
call void [MyIlApp]MyIlApp.MainClass::check(int32)

/* Test Case 2 */


// VC vc1;
.locals init ([2] valuetype [MyIlApp]MyIlApp.VC vc1)

// vc1.val_string = "Test string of VC";
ldloca.s 2
ldstr "Test string of VC"
stfld string MyIlApp.VC::val_string

// vc1.val_int32 = 8;
ldloca.s 2
ldc.i4.8
stfld int32 MyIlApp.VC::val_int32

// System.Console.WriteLine(vc1.val_string);
ldloca.s 2
ldfld string MyIlApp.VC::val_string
call void [mscorlib]System.Console::WriteLine(string)

// System.Console.WriteLine(vc1.val_int32.ToString()); // 《Expert .NET 2.0 IL Assembler》上说 ldflda “不能使用值类型的实例,也不能获取指向值类型实例的对象引用或指针”,有误。为了实现类似 a.X = 100(a 为 System.Drawing.Point 类型)这样的调用,需要用到 call 指令,也就需要用到 ldflda 而不是 ldfld;不过后者可以用在不访问实例函数/字段的情况下
ldloca.s 2
ldflda int32 MyIlApp.VC::val_int32
call instance string [mscorlib]System.Int32::ToString()
call void [mscorlib]System.Console::WriteLine(string)

// return;
ret
}

}
}
分享到 评论