详解.net中IL语言
什么是IL语言
中间语言,又称(IL语言)。充当Clr与.net 平台的中间语言,比如用C#编写程序,编译器首先是把C#代码转译成IL语言,最终由Clr解释执行,下面我们学习下IL语言。
如何读懂IL语言
写一个helloworld的.net 程序,编译运行完成。
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
141
142
143
144static void Main(string[] args)
{
Console.WriteLine("hello world");
}
```
- 使用ildasm.exe(C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools)反编译代码,得到IL代码如下:
```IL
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "hello world"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Program::Main
```
- 查找对应的[指令表](http://blog.csdn.net/xiaouncle/article/details/71248830),来确定对应的含义
<table class="table">
<thead>
<tr>
<th>指令名称</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ldstr</td>
<td>推送对元数据中存储的字符串的新对象引用。</td>
</tr>
<tr>
<td>Nop</td>
<td>如果修补操作码,则填充空间。尽管可能消耗处理周期,但未执行任何有意义的操作。</td>
</tr>
<tr>
<td>Call</td>
<td>调用由传递的方法说明符指示的方法。</td>
</tr>
<tr>
<td>Ret</td>
<td>从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。</td>
</tr>
</tbody>
</table>
- 其它几个名词的的解释
**hidebysig**: 与之对就的是hidebyname,这个是确定使用方法的签名还是使用方法的名称来确定调用哪个方法.
- 整个的IL语言解释
```IL
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint //代码入口
// 代码大小 13 (0xd)
.maxstack 8 //整个程序的堆栈大小
IL_0000: nop //无实在意义
IL_0001: ldstr "hello world" //定义字符
IL_0006: call void [mscorlib]System.Console::WriteLine(string) //调用WriteLine变量
IL_000b: nop
IL_000c: ret //返回
} // end of method Program::Main
```
- 添加编写如下C
``` C
class Program
{
static void Main(string[] args)
{
var a = 0;
var b = 1;
var c = Add(a, b);
Console.WriteLine(c.ToString());
}
public static int Add(int x,int y)
{
return x + y;
}
}
```
- 生成相关的IL代码及解释
``` IL
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 27 (0x1b)
.maxstack 2
.locals init ([0] int32 a,
[1] int32 b,
[2] int32 c) //定义3个变量
IL_0000: nop
IL_0001: ldc.i4.0 //将整数值 0 作为 int32 推送到计算堆栈上。
IL_0002: stloc.0 //从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。
IL_0003: ldc.i4.1 //将整数值 1 作为 int32 推送到计算堆栈上。
IL_0004: stloc.1 //从计算堆栈的顶部弹出当前值并将其存储到索引 1 处的局部变量列表中。
IL_0005: ldloc.0 //将索引 0 处的局部变量加载到计算堆栈上,这里指a。
IL_0006: ldloc.1 //将索引 1 处的局部变量加载到计算堆栈上,这里指b。
IL_0007: call int32 ILTest.Program::Add(int32,
int32) //调用Add方法
IL_000c: stloc.2 //将索引 2 处的局部变量加载到计算堆栈上,这里指c。
IL_000d: ldloca.s c //将位于特定索引处的局部变量的地址加载到计算堆栈上(短格式)。
IL_000f: call instance string [mscorlib]System.Int32::ToString()
IL_0014: call void [mscorlib]System.Console::WriteLine(string)
IL_0019: nop
IL_001a: ret
} // end of method Program::Main
```
Add方法:
``` IL
.method public hidebysig static int32 Add(int32 x,int32 y) cil managed
{
// 代码大小 9 (0x9)
.maxstack 2
.locals init ([0] int32 V_0) //创建一个V_0的局部变量
IL_0000: nop
IL_0001: ldarg.0 //将索引为 0 的参数加载到计算堆栈上。
IL_0002: ldarg.1 //将索引为 1 的参数加载到计算堆栈上。
IL_0003: add //将两个值相加并将结果推送到计算堆栈上。
IL_0004: stloc.0
IL_0005: br.s IL_0007 //无条件地将控制转移到目标指令(短格式)
IL_0007: ldloc.0 //将索引 0 处的局部变量加载到计算堆栈上。
IL_0008: ret
} // end of method Program::Add