Why is there ldloc.0 right after stloc.0 in IL code?
I am 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 the 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, it stloc
pushes the topmost value from the evaluation stack into a local variable, and if I understood correctly, that value did not slip off the stack, so why does the compiler put it ldloc
right after it?
source to share
It is only in debug mode that you see these instructions as the compiler does not optimize the code so you can debug and place breakpoints at specific parts.
If you compile this application in Release mode, you will see that there are optimizations even in the IL code.
.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
source to share