Emit基础学习-选择分支
2009-07-13 09:51 Kevin-wang 阅读(389) 评论(0) 编辑 收藏 举报C#代码
int sum = 0;
if (num1 > 0)
{
sum = num1 + 100;
}
if (num1 > 0)
{
sum = num1 + 100;
}
IL代码
.maxstack 2
.locals init (
[0] int32 num,
[1] bool flag)
L_0000: ldc.i4.0
L_0001: stloc.0
L_0002: ldc.i4.0
L_0003: stloc.1
L_0004: ldarg.0
L_0005: ldc.i4.0
L_0006: cgt
L_0008: ldc.i4.0
L_0009: ceq
L_000b: stloc.1
L_000c: ldloc.1
L_000d: brtrue.s L_0017
L_000f: ldarg.0
L_0010: ldc.i4 100
L_0015: add
L_0016: stloc.0
L_0017: ret
.locals init (
[0] int32 num,
[1] bool flag)
L_0000: ldc.i4.0
L_0001: stloc.0
L_0002: ldc.i4.0
L_0003: stloc.1
L_0004: ldarg.0
L_0005: ldc.i4.0
L_0006: cgt
L_0008: ldc.i4.0
L_0009: ceq
L_000b: stloc.1
L_000c: ldloc.1
L_000d: brtrue.s L_0017
L_000f: ldarg.0
L_0010: ldc.i4 100
L_0015: add
L_0016: stloc.0
L_0017: ret
Emit代码
_Method = _TypeBuilder.DefineMethod("Dotest4",
MethodAttributes.Public |MethodAttributes.Static,
null,new Type[] { typeof(int) });
_MethodIL = _Method.GetILGenerator();
l1 = _MethodIL.DefineLabel();
// l2 = _MethodIL.DefineLabel();
//int _Sum=0;
LocalBuilder _v1 = _MethodIL.DeclareLocal(typeof(int));
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Stloc_0);
LocalBuilder _v2 = _MethodIL.DeclareLocal(typeof(bool));
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Stloc_1);
_MethodIL.Emit(OpCodes.Ldarg_0);
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Cgt);
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Ceq);
_MethodIL.Emit(OpCodes.Stloc_1);
_MethodIL.Emit(OpCodes.Ldloc_1);
_MethodIL.Emit(OpCodes.Brtrue_S, l1);
//_sum=pNum+100;
_MethodIL.Emit(OpCodes.Ldarg_0);
_MethodIL.Emit(OpCodes.Ldc_I4, 100);
_MethodIL.Emit(OpCodes.Add);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.MarkLabel(l1);
_MethodIL.Emit(OpCodes.Ret);
MethodAttributes.Public |MethodAttributes.Static,
null,new Type[] { typeof(int) });
_MethodIL = _Method.GetILGenerator();
l1 = _MethodIL.DefineLabel();
// l2 = _MethodIL.DefineLabel();
//int _Sum=0;
LocalBuilder _v1 = _MethodIL.DeclareLocal(typeof(int));
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Stloc_0);
LocalBuilder _v2 = _MethodIL.DeclareLocal(typeof(bool));
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Stloc_1);
_MethodIL.Emit(OpCodes.Ldarg_0);
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Cgt);
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Ceq);
_MethodIL.Emit(OpCodes.Stloc_1);
_MethodIL.Emit(OpCodes.Ldloc_1);
_MethodIL.Emit(OpCodes.Brtrue_S, l1);
//_sum=pNum+100;
_MethodIL.Emit(OpCodes.Ldarg_0);
_MethodIL.Emit(OpCodes.Ldc_I4, 100);
_MethodIL.Emit(OpCodes.Add);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.MarkLabel(l1);
_MethodIL.Emit(OpCodes.Ret);
C#代码—条件表达式
使用Emit生成IL后反射的C#代码
return ((num1 > 100) ? -1 : 0);
手工编写的代码
return ((num > 100) ? -1 : 0);
IL代码
使用Emit生成的IL代码
.maxstack 3
L_0000: ldarg.0
L_0001: ldc.i4.s 100
L_0003: nop
L_0004: nop
L_0005: nop
L_0006: bgt.s L_000b
L_0008: ldc.i4.0
L_0009: br.s L_000c
L_000b: ldc.i4.m1
L_000c: ret
L_0000: ldarg.0
L_0001: ldc.i4.s 100
L_0003: nop
L_0004: nop
L_0005: nop
L_0006: bgt.s L_000b
L_0008: ldc.i4.0
L_0009: br.s L_000c
L_000b: ldc.i4.m1
L_000c: ret
手工编写的代生成的IL代码
.maxstack 2
.locals init (
[0] int32 CS$1$0000)
L_0000: nop
L_0001: ldarg.0
L_0002: ldc.i4.s 100
L_0004: bgt.s L_0009
L_0006: ldc.i4.0
L_0007: br.s L_000a
L_0009: ldc.i4.m1
L_000a: stloc.0
L_000b: br.s L_000d
L_000d: ldloc.0
L_000e: ret
.locals init (
[0] int32 CS$1$0000)
L_0000: nop
L_0001: ldarg.0
L_0002: ldc.i4.s 100
L_0004: bgt.s L_0009
L_0006: ldc.i4.0
L_0007: br.s L_000a
L_0009: ldc.i4.m1
L_000a: stloc.0
L_000b: br.s L_000d
L_000d: ldloc.0
L_000e: ret
Emit代码
_Method = _TypeBuilder.DefineMethod("Dotest1",MethodAttributes.Public | MethodAttributes.Static,
typeof(int), new Type[] { typeof(int) });
_MethodIL = _Method.GetILGenerator();
failed = _MethodIL.DefineLabel();
endOfMthd = _MethodIL.DefineLabel();
//生成代码
//if (num1 > 100)
//将索引为 0 的参数加载到计算堆栈上。
_MethodIL.Emit(OpCodes.Ldarg_0);
//将提供的 int8 值作为 int32 推送到计算堆栈上
_MethodIL.Emit(OpCodes.Ldc_I4_S, 100);
//如果第一个值大于第二个值,则将控制转移到目标指令
_MethodIL.Emit(OpCodes.Bgt_S, failed);
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Br_S, endOfMthd);
_MethodIL.MarkLabel(failed);
_MethodIL.Emit(OpCodes.Ldc_I4_M1);
_MethodIL.MarkLabel(endOfMthd);
_MethodIL.Emit(OpCodes.Ret);
typeof(int), new Type[] { typeof(int) });
_MethodIL = _Method.GetILGenerator();
failed = _MethodIL.DefineLabel();
endOfMthd = _MethodIL.DefineLabel();
//生成代码
//if (num1 > 100)
//将索引为 0 的参数加载到计算堆栈上。
_MethodIL.Emit(OpCodes.Ldarg_0);
//将提供的 int8 值作为 int32 推送到计算堆栈上
_MethodIL.Emit(OpCodes.Ldc_I4_S, 100);
//如果第一个值大于第二个值,则将控制转移到目标指令
_MethodIL.Emit(OpCodes.Bgt_S, failed);
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Br_S, endOfMthd);
_MethodIL.MarkLabel(failed);
_MethodIL.Emit(OpCodes.Ldc_I4_M1);
_MethodIL.MarkLabel(endOfMthd);
_MethodIL.Emit(OpCodes.Ret);
Switch分支
C#代码
switch (num1)
{
case 4:
return 30;
case 7:
return 0x1f;
case 8:
return 0x1d;
}
return 0x1c;
{
case 4:
return 30;
case 7:
return 0x1f;
case 8:
return 0x1d;
}
return 0x1c;
生成的IL代码
.method public static int32 Dotest5(int32) cil managed
{
.maxstack 7
.locals init (
[0] int32 num,
[1] int32 num2,
[2] int32 num3)
L_0000: nop
L_0001: ldc.i4.0
L_0002: stloc.0
L_0003: ldarg.0
L_0004: stloc.2
L_0005: ldloc.2
L_0006: ldc.i4.4
L_0007: beq.s L_0013
L_0009: ldloc.2
L_000a: ldc.i4.7
L_000b: beq.s L_001b
L_000d: ldloc.2
L_000e: ldc.i4.8
L_000f: beq.s L_0023
L_0011: br.s L_002b
L_0013: ldc.i4.s 30
L_0015: nop
L_0016: nop
L_0017: nop
L_0018: stloc.0
L_0019: br.s L_0033
L_001b: ldc.i4.s 0x1f
L_001d: nop
L_001e: nop
L_001f: nop
L_0020: stloc.0
L_0021: br.s L_0033
L_0023: ldc.i4.s 0x1d
L_0025: nop
L_0026: nop
L_0027: nop
L_0028: stloc.0
L_0029: br.s L_0033
L_002b: ldc.i4.s 0x1c
L_002d: nop
L_002e: nop
L_002f: nop
L_0030: stloc.0
L_0031: br.s L_0033
L_0033: ldloc.0
L_0034: ret
}
{
.maxstack 7
.locals init (
[0] int32 num,
[1] int32 num2,
[2] int32 num3)
L_0000: nop
L_0001: ldc.i4.0
L_0002: stloc.0
L_0003: ldarg.0
L_0004: stloc.2
L_0005: ldloc.2
L_0006: ldc.i4.4
L_0007: beq.s L_0013
L_0009: ldloc.2
L_000a: ldc.i4.7
L_000b: beq.s L_001b
L_000d: ldloc.2
L_000e: ldc.i4.8
L_000f: beq.s L_0023
L_0011: br.s L_002b
L_0013: ldc.i4.s 30
L_0015: nop
L_0016: nop
L_0017: nop
L_0018: stloc.0
L_0019: br.s L_0033
L_001b: ldc.i4.s 0x1f
L_001d: nop
L_001e: nop
L_001f: nop
L_0020: stloc.0
L_0021: br.s L_0033
L_0023: ldc.i4.s 0x1d
L_0025: nop
L_0026: nop
L_0027: nop
L_0028: stloc.0
L_0029: br.s L_0033
L_002b: ldc.i4.s 0x1c
L_002d: nop
L_002e: nop
L_002f: nop
L_0030: stloc.0
L_0031: br.s L_0033
L_0033: ldloc.0
L_0034: ret
}
Emit生成代码
_Method = _TypeBuilder.DefineMethod("Dotest5",
MethodAttributes.Public | MethodAttributes.Static,
typeof(int), new Type[] { typeof(int) });
_MethodIL = _Method.GetILGenerator();
Label[] _Lbls = new Label[3];
//默认(switch语句的default节点)
Label _defaultLabel = _MethodIL.DefineLabel();
//endswitch
Label _endswitch = _MethodIL.DefineLabel();
Label _endswitch2 = _MethodIL.DefineLabel();
for (int i = 0; i < _Lbls.Length; i++)
{
_Lbls[i] = _MethodIL.DefineLabel();
}
//声明变量
//int result=0;
LocalBuilder _result = _MethodIL.DeclareLocal(typeof(int));
LocalBuilder _num1 = _MethodIL.DeclareLocal(typeof(int));
LocalBuilder _num2 = _MethodIL.DeclareLocal(typeof(int));
_MethodIL.Emit(OpCodes.Nop);
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Ldarg_0);
_MethodIL.Emit(OpCodes.Stloc_2);
//_MethodIL.Emit(OpCodes.Switch, _Lbls);
// L_0005: ldloc.2
//L_0006: ldc.i4.4
//L_0007: beq.s L_000f //如果两个值相等,则将控制转移到目标指令。
_MethodIL.Emit(OpCodes.Ldloc_2);
_MethodIL.Emit(OpCodes.Ldc_I4_4);
_MethodIL.Emit(OpCodes.Beq_S, _Lbls[0]);
_MethodIL.Emit(OpCodes.Ldloc_2);
_MethodIL.Emit(OpCodes.Ldc_I4_7);
_MethodIL.Emit(OpCodes.Beq_S, _Lbls[1]);
_MethodIL.Emit(OpCodes.Ldloc_2);
_MethodIL.Emit(OpCodes.Ldc_I4_8);
_MethodIL.Emit(OpCodes.Beq_S, _Lbls[2]);
_MethodIL.Emit(OpCodes.Br_S, _defaultLabel);
_MethodIL.MarkLabel(_Lbls[0]);
_MethodIL.Emit(OpCodes.Ldc_I4_S, 30);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Br_S, _endswitch);
_MethodIL.MarkLabel(_Lbls[1]);
_MethodIL.Emit(OpCodes.Ldc_I4_S, 31);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Br_S, _endswitch);
_MethodIL.MarkLabel(_Lbls[2]);
_MethodIL.Emit(OpCodes.Ldc_I4_S, 29);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Br_S, _endswitch);
_MethodIL.MarkLabel(_defaultLabel);
_MethodIL.Emit(OpCodes.Ldc_I4_S, 28);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Br_S, _endswitch);
_MethodIL.MarkLabel(_endswitch);
_MethodIL.Emit(OpCodes.Ldloc_0);
_MethodIL.Emit(OpCodes.Ret);
MethodAttributes.Public | MethodAttributes.Static,
typeof(int), new Type[] { typeof(int) });
_MethodIL = _Method.GetILGenerator();
Label[] _Lbls = new Label[3];
//默认(switch语句的default节点)
Label _defaultLabel = _MethodIL.DefineLabel();
//endswitch
Label _endswitch = _MethodIL.DefineLabel();
Label _endswitch2 = _MethodIL.DefineLabel();
for (int i = 0; i < _Lbls.Length; i++)
{
_Lbls[i] = _MethodIL.DefineLabel();
}
//声明变量
//int result=0;
LocalBuilder _result = _MethodIL.DeclareLocal(typeof(int));
LocalBuilder _num1 = _MethodIL.DeclareLocal(typeof(int));
LocalBuilder _num2 = _MethodIL.DeclareLocal(typeof(int));
_MethodIL.Emit(OpCodes.Nop);
_MethodIL.Emit(OpCodes.Ldc_I4_0);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Ldarg_0);
_MethodIL.Emit(OpCodes.Stloc_2);
//_MethodIL.Emit(OpCodes.Switch, _Lbls);
// L_0005: ldloc.2
//L_0006: ldc.i4.4
//L_0007: beq.s L_000f //如果两个值相等,则将控制转移到目标指令。
_MethodIL.Emit(OpCodes.Ldloc_2);
_MethodIL.Emit(OpCodes.Ldc_I4_4);
_MethodIL.Emit(OpCodes.Beq_S, _Lbls[0]);
_MethodIL.Emit(OpCodes.Ldloc_2);
_MethodIL.Emit(OpCodes.Ldc_I4_7);
_MethodIL.Emit(OpCodes.Beq_S, _Lbls[1]);
_MethodIL.Emit(OpCodes.Ldloc_2);
_MethodIL.Emit(OpCodes.Ldc_I4_8);
_MethodIL.Emit(OpCodes.Beq_S, _Lbls[2]);
_MethodIL.Emit(OpCodes.Br_S, _defaultLabel);
_MethodIL.MarkLabel(_Lbls[0]);
_MethodIL.Emit(OpCodes.Ldc_I4_S, 30);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Br_S, _endswitch);
_MethodIL.MarkLabel(_Lbls[1]);
_MethodIL.Emit(OpCodes.Ldc_I4_S, 31);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Br_S, _endswitch);
_MethodIL.MarkLabel(_Lbls[2]);
_MethodIL.Emit(OpCodes.Ldc_I4_S, 29);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Br_S, _endswitch);
_MethodIL.MarkLabel(_defaultLabel);
_MethodIL.Emit(OpCodes.Ldc_I4_S, 28);
_MethodIL.Emit(OpCodes.Stloc_0);
_MethodIL.Emit(OpCodes.Br_S, _endswitch);
_MethodIL.MarkLabel(_endswitch);
_MethodIL.Emit(OpCodes.Ldloc_0);
_MethodIL.Emit(OpCodes.Ret);