. NET (C #): Parse If-else,while and for statements in IL and implement them with emit

Source: Internet
Author: User
Tags emit mscorlib

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.