This is an article about IL and reflection emit (so do not like IL or emit do not need to look down), ask the reader to the IL and emit working principle more understanding. All analysis Il is compiled and generated under visual Studio SP1. (Other compilers do not necessarily have the same 100% result but are logically equivalent, and hope the reader learns "why", not "what").
Directory
- Analysis If-else
- Emit creating If-else Dynamic methods
- Analysis while
- Emit creating a while dynamic method
- Analysis for
- Emit creating a For dynamic method
Back to Catalog
Analysis If-else
If-else in C #:
if (condition)
to True Code
Else
to False code
Il execution logic for if-else:
Condition is true: Goto true
False
False code
Goto exit
Really
True Code
Exit
To parse an example program:
C#:
static void Doo (bool b)
{
if (b)
Console.WriteLine (1);
Else
Console.WriteLine (2);
}
IL:
. maxstack 2
. Locals Init (
[0] bool cs$4$0000)
l_0001:ldarg.0 //b into the stack
l_0002:ldc.i4.0 //0 (false) into the stack
L_0003:CEQ //compare B and False
l_0005:stloc.0 //Assign the result to a temporary bool
l_0006:ldloc.0 //load BOOL
L_0007:BRTRUE.S l_0012 //If False, skip to l_0012
l_0009:ldc.i4.1 //true Code
L_000a:call void [Mscorlib]system.console::writeline (Int32)
L_000f:nop
L_0010:BR.S l_0019//Jump to back
l_0012:ldc.i4.2 //false Code
L_0013:call void [Mscorlib]system.console::writeline (Int32)
L_0019:ret//Return
Back to Catalog
Emit creating If-else Dynamic methods
With the knowledge above, you can create a dynamic method that has a if-else statement, such as a method:
static void Test (BOOL b)
{
if (b)
Console.WriteLine ("true");
Else
Console.WriteLine ("false");
}
Create and run using reflection Emit, code:
//+ using System.Reflection;
//+ using System.Reflection.Emit;
static void Main (string[] args)
{
//Create DynamicMethod object
var dm = Getifelse ();
//Test
DM. Invoke (NULL, new object[] {true});
DM. Invoke (NULL, new object[] {false});
}
static DynamicMethod getifelse ()
{
var dm = new DynamicMethod ("", NULL, new type[] {typeof (BOOL)} );
var gen = dm. GetILGenerator ();
Label lbfalse = Gen. Definelabel ();
Label Lbret = Gen. Definelabel ();
//Judge
Gen. Emit (OPCODES.LDARG_0);
Gen. Emit (OPCODES.LDC_I4, 1);
Gen. Emit (OPCODES.CEQ);
//If False: Skip to False code
Gen. Emit (Opcodes.brfalse, Lbfalse);
//true Code
Gen. Emitwriteline ("true");
//Skip to exit
Gen. Emit (opcodes.br, Lbret);
//false Code
Gen. Marklabel (Lbfalse);
Gen. Emitwriteline ("false");
//Exit code
Gen. Marklabel (Lbret);
Gen. Emit (Opcodes.ret);
return DM;
}
Output:
Really
False
Ok!
Back to Catalog
Analysis while
While in C #:
while (condition)
{
True Code
}
Il in while execution logic:
Goto judgment
Really
True Code
Judge
Condition is true: Goto true
Parsing code, C #:
static void Doo (bool b)
{
while (b)
{
Console.WriteLine ("TRUE");
}
}
IL:
. maxstack 1
. Locals Init (
[0] bool cs$4$0000)
L_0001:BR.S l_0010 //Jump to judgment
L_0003:nop //true Code
L_0009:call void [Mscorlib]system.console::writeline (String)
l_0010:ldarg.0 //Start judging, load B
l_0012:ldloc.0 //assigns the value of B to a temporary variable
L_0013:BRTRUE.S l_0003//If True, jump to True code
Back to Catalog
Emit creating a while dynamic method
If you understand that, creating a while loop is very simple, and we will dynamically create such a method:
static void Test (BOOL b)
{
if (b)
Console.WriteLine ("TRUE");
}
Code:
+ using System.Reflection;
+ using System.Reflection.Emit;
static void Main (string[] args)
{
Create a DynamicMethod object
var dm = Getwhile ();
Test
Dm. Invoke (NULL, new object[] {false});
Console.WriteLine ("Parameter false, end, wait 3 seconds after running parameter true");
System.Threading.Thread.Sleep (3000);
Dm. Invoke (NULL, new object[] {true});
}
Static DynamicMethod Getwhile ()
{
var dm = new DynamicMethod ("", NULL, new type[] {typeof (BOOL)});
var Gen = dm. GetILGenerator ();
Label lbcondition = Gen. Definelabel ();
Label lbtrue = Gen. Definelabel ();
Jump to judgment
Gen. Emit (opcodes.br, lbcondition);
Mark True Code
Gen. Marklabel (lbtrue);
Gen. Emitwriteline ("TRUE");
Tag Judgment Code
Gen. Marklabel (lbcondition);
Judge
Gen. Emit (OPCODES.LDARG_0);
Gen. Emit (OPCODES.LDC_I4, 1);
Gen. Emit (OPCODES.CEQ);
If true, jump to True code
Gen. Emit (Opcodes.brtrue, lbtrue);
Gen. Emit (Opcodes.ret);
return DM;
}
Program output, of course false parameter does not have any output, and then wait 3 seconds after infinite output true
Parameter false, end, wait 3 seconds after running parameter true
TRUE
TRUE
TRUE
TRUE
...
Back to Catalog
Analysis for
For in C #
for (definition; judgment; append action)
{
Action
}
Il in for execution logic:
Goto judgment
Action
Append action
Judge
Condition is true: Goto action
Oh, seemingly complex for loop is actually very simple.
Analysis Code:
for (int i = 0; i <; i++)
{
Console.WriteLine (i);
}
IL:
. maxstack 2
. Locals Init (
[0] int32 I,
[1] bool cs$4$0000)
l_0001:ldc.i4.0
l_0002:stloc.0 //i=0
L_0003:BR.S l_0012 //Jump to judgment
L_0005:nop //true Code
l_0006:ldloc.0 //action code
L_0007:call void [Mscorlib]system.console::writeline (Int32)
L_000c:nop //Action code end
L_000d:nop //Append action code
l_000e:ldloc.0 //i++
l_0011:stloc.0 //Update I, Append action code end
l_0012:ldloc.0 //Judgment code
L_0013:LDC.I4.S 10//10 into the stack
L_0015:CLT //<= judgment instruction, determine if I is less than 10
L_0018:LDLOC.1 //storing results in temporary local bool variable
L_0019:BRTRUE.S l_0005 //If True, jump to True code
Back to Catalog
Emit creating a For dynamic method
We will dynamically create such a method:
static void Test (int c)
{
for (int i = 0; i < C; i++)
{
Console.WriteLine (i);
}
}
Code:
+ using System.Reflection;
+ using System.Reflection.Emit;
static void Main (string[] args)
{
Create a DynamicMethod object
var dm = getfor ();
Test
Dm. Invoke (NULL, new object[] {3});
}
Static DynamicMethod getfor ()
{
var dm = new DynamicMethod ("", NULL, new type[] {typeof (int)});
var Gen = dm. GetILGenerator ();
Temp variable i
LocalBuilder loci = Gen. DeclareLocal (typeof (int));
Label lbcondition = Gen. Definelabel ();
Label lbtrue = Gen. Definelabel ();
I=0
Gen. Emit (OPCODES.LDC_I4_0);
Gen. Emit (Opcodes.stloc, loci);
Jump to judgment
Gen. Emit (opcodes.br, lbcondition);
Mark True Code
Gen. Marklabel (lbtrue);
Console.WriteLine (i)
Gen. Emit (Opcodes.ldloc, loci);
Gen. Emit (Opcodes.call, typeof (Console). GetMethod ("WriteLine", new type[] {typeof (int)}));
Append code
i++
Gen. Emit (Opcodes.ldloc, loci);
Gen. Emit (Opcodes.ldc_i4_1);
Gen. Emit (Opcodes.add);
Gen. Emit (Opcodes.stloc, loci);
Judging the Code
Gen. Marklabel (lbcondition);
Gen. Emit (Opcodes.ldloc, loci);
Gen. Emit (OPCODES.LDARG_0);
Gen. Emit (OPCODES.CLT);
If true, jump to True code
Gen. Emit (Opcodes.brtrue, lbtrue);
Gen. Emit (Opcodes.ret);
return DM;
}
Output:
0
1
2
Transferred from: https://www.mgenware.com/blog/?p=90
. NET (C #): Parse If-else,while and for statements in IL and implement them with emit