Emit基础学习-选择分支

 

 

C#代码

int  sum  =   0 ;
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  

 

 

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);



 

 

 

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


手工编写的代生成的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


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);




 

 

Switch分支

C#代码

switch  (num1)
{
    
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  
}



 

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);

 

你可能感兴趣的:(it)