I`m trying to learn CIL by writing small snippets of code and examining compiled assemblies. So I wrote this simple if statement:
public static void Main (string[] args)
{
Int32 i = Int32.Parse (Console.ReadLine());
if (i > 0)
Console.WriteLine ("i is greater than 0");
}
And C# compiler compiled it into the following IL code:
.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
}
As I know,stloc
puts the topmost value from the evaluation stack into the local variable,and,if I got it right,that value isn`t popped from the stack,so why does the compiler puts the ldloc
instruction just after it?
It's only in Debug mode that you see those instructions as the compiler doesn't optimize the code so that you can debug and put breakpoints in specific parts.
If you compile this application in Release mode you see that even on IL code there's an optimization is done.
.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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With