我正在尝试通过编写小型代码段并检查编译的组件来学习CIL。所以我写了这个简单的语句:
public static void Main (string[] args)
{
Int32 i = Int32.Parse (Console.ReadLine());
if (i > 0)
Console.WriteLine ("i is greater than 0");
}
和C#编译器将其编译为以下IL代码:
.method public hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 num,
[1] bool flag)
L_0000: nop
L_0001: call string [mscorlib]System.Console::ReadLine()
L_0006: call int32 [mscorlib]System.Int32::Parse(string)
L_000b: stloc.0
L_000c: ldloc.0
L_000d: ldc.i4.0
L_000e: cgt
L_0010: ldc.i4.0
L_0011: ceq
L_0013: stloc.1
L_0014: ldloc.1
L_0015: brtrue.s L_0022
L_0017: ldstr "i is greater than 0"
L_001c: call void [mscorlib]System.Console::WriteLine(string)
L_0021: nop
L_0022: ret
}
我知道,stloc
将评估堆栈中的最高值放入本地变量中,如果我正确地知道,该值不会从堆栈中弹出,那么为什么编译器在后面将ldloc
指令放在它?
只有在调试模式下,您才能将这些指令视为编译器不会优化代码,以便您可以调试并将断点放在特定的部分中。
如果您以发布模式编译此应用程序,您会发现即使在IL代码上也可以进行优化。
.method public hidebysig static void
Main(
string[] args
) cil managed
{
.entrypoint
.maxstack 8
// [13 13 - 13 55]
IL_0000: call string [mscorlib]System.Console::ReadLine()
IL_0005: call int32 [mscorlib]System.Int32::Parse(string)
// [14 13 - 14 23]
IL_000a: ldc.i4.0
IL_000b: ble.s IL_0017
// [15 17 - 15 58]
IL_000d: ldstr "i is greater than 0"
IL_0012: call void [mscorlib]System.Console::WriteLine(string)
// [16 9 - 16 10]
IL_0017: ret
} // end of method Program::Main