这一篇讲的是怎样加载整数值到运算栈上。这一类的指令都是以Ldc_I4开头。
Ldc_I4
类OpCodes的Ldc_I4字段的功能是把一个int值压入运算栈上。它的使用方法是
ilGenerator.Emit(OpCodes.Ldc_I4, <整数值>);
产生的指令是ldc.i4 <整数值>
几个例子
ilGenerator.Emit(OpCodes.Ldc_I4, 2000);//ldc.i4 2000 ilGenerator.Emit(OpCodes.Ldc_I4, -100);//ldc.i4 -100 ilGenerator.Emit(OpCodes.Ldc_I4, -1);//ldc.i4 -1
Ldc_I4_S
类OpCodes的Ldc_I4_S字段的功能是把一个将从-128 到 127 之间的整数值压入运算栈上。如果整数值小于0,则必须强制转换为sbyte。它的使用方法是
ilGenerator.Emit(OpCodes.Ldc_I4_S <整数值>);
产生的指令是ldc.i4 <整数值>
几个例子
ilGenerator.Emit(OpCodes.Ldc_I4_S, (SByte)(-1));//ldc.i4.s -1 ilGenerator.Emit(OpCodes.Ldc_I4_S, 127);//ldc.i4.s 127 ilGenerator.Emit(OpCodes.Ldc_I4_S, 0);//ldc.i4.s 0
Ldc_I4_M1、Ldc_I4_0、Ldc_I4_1、Ldc_I4_2、Ldc_I4_3、Ldc_I4_4、Ldc_I4_5、Ldc_I4_6、Ldc_I4_7、Ldc_I4_8
Ldc_I4_M1作用是将-1推送到计算堆栈上,Ldc_I4_0作用是将0推送到计算堆栈上,Ldc_I4_1作用是将1推送到计算堆栈上,Ldc_I4_2作用是将2推送到计算堆栈上,Ldc_I4_3作用是将3推送到计算堆栈上,Ldc_I4_4作用是将4推送到计算堆栈上,Ldc_I4_5作用是将5推送到计算堆栈上,Ldc_I4_6作用是将6推送到计算堆栈上,Ldc_I4_7作用是将7推送到计算堆栈上,Ldc_I4_8作用是将8推送到计算堆栈上。
它们的使用方法是
ilGenerator.Emit(OpCodes.Ldc_I4_M1);//ldc.i4.m1 ilGenerator.Emit(OpCodes.Ldc_I4_0);//ldc.i4.0 ilGenerator.Emit(OpCodes.Ldc_I4_1);//ldc.i4.1 ilGenerator.Emit(OpCodes.Ldc_I4_2);//ldc.i4.2 ilGenerator.Emit(OpCodes.Ldc_I4_3);//ldc.i4.3 ilGenerator.Emit(OpCodes.Ldc_I4_4);//ldc.i4.4 ilGenerator.Emit(OpCodes.Ldc_I4_5);//ldc.i4.5 ilGenerator.Emit(OpCodes.Ldc_I4_6);//ldc.i4.6 ilGenerator.Emit(OpCodes.Ldc_I4_7);//ldc.i4.7 ilGenerator.Emit(OpCodes.Ldc_I4_8);//ldc.i4.8
ilGenerator.Emit(OpCodes.Ldc_I4_M1)和ilGenerator.Emit(OpCodes.Ldc_I4, -1)、ilGenerator.Emit(OpCodes.Ldc_I4_S, (SByte)(-1))运行的结果是一条的,但是效率更高;同样的ilGenerator.Emit(OpCodes.Ldc_I4_0)和ilGenerator.Emit(OpCodes.Ldc_I4, 0)、ilGenerator.Emit(OpCodes.Ldc_I4_S, 0)运行结果一样,效率更高,等等。
在-128 到 127 之间的整数值用Ldc_I4_S比Ldc_I4更好。
所以可以把加载整数值用一个方法代替
public static void LoadInt(ILGenerator il, int value) { switch (value) { case -1: il.Emit(OpCodes.Ldc_I4_M1); return; case 0: il.Emit(OpCodes.Ldc_I4_0); return; case 1: il.Emit(OpCodes.Ldc_I4_1); return; case 2: il.Emit(OpCodes.Ldc_I4_2); return; case 3: il.Emit(OpCodes.Ldc_I4_3); return; case 4: il.Emit(OpCodes.Ldc_I4_4); return; case 5: il.Emit(OpCodes.Ldc_I4_5); return; case 6: il.Emit(OpCodes.Ldc_I4_6); return; case 7: il.Emit(OpCodes.Ldc_I4_7); return; case 8: il.Emit(OpCodes.Ldc_I4_8); return; } if (value > -129 && value < 128) { il.Emit(OpCodes.Ldc_I4_S, (SByte)value); } else { il.Emit(OpCodes.Ldc_I4, value); } }
完整的程序如下
using System; using System.Reflection; using System.Reflection.Emit; namespace LX1_ILDemo { class Demo1_LoadIntIL { static string binaryName = "LoadIntDemo.exe"; static string namespaceName = "LX1_ILDemo"; static string typeName = "LoadInt"; static AssemblyBuilder assemblyBuilder; static ModuleBuilder moduleBuilder; static TypeBuilder typeBuilder; static MethodBuilder mainMethod; static ILGenerator ilGenerator; static MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }); public static void LoadInt(ILGenerator il, int value) { switch (value) { case -1: il.Emit(OpCodes.Ldc_I4_M1); return; case 0: il.Emit(OpCodes.Ldc_I4_0); return; case 1: il.Emit(OpCodes.Ldc_I4_1); return; case 2: il.Emit(OpCodes.Ldc_I4_2); return; case 3: il.Emit(OpCodes.Ldc_I4_3); return; case 4: il.Emit(OpCodes.Ldc_I4_4); return; case 5: il.Emit(OpCodes.Ldc_I4_5); return; case 6: il.Emit(OpCodes.Ldc_I4_6); return; case 7: il.Emit(OpCodes.Ldc_I4_7); return; case 8: il.Emit(OpCodes.Ldc_I4_8); return; } if (value > -129 && value < 128) { il.Emit(OpCodes.Ldc_I4_S, (SByte)value); } else { il.Emit(OpCodes.Ldc_I4, value); } } /// <summary> /// Ldc_I4_*类指令生成 /// </summary> static void Emit_Ldc_I4_X() { /* 生成 Console.WriteLine(-1); */ ilGenerator.Emit(OpCodes.Ldc_I4_M1);//ldc.i4.m1 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(0); */ ilGenerator.Emit(OpCodes.Ldc_I4_0);//ldc.i4.0 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(1); */ ilGenerator.Emit(OpCodes.Ldc_I4_1);//ldc.i4.1 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(2); */ ilGenerator.Emit(OpCodes.Ldc_I4_2);//ldc.i4.2 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(3); */ ilGenerator.Emit(OpCodes.Ldc_I4_3);//ldc.i4.3 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(4); */ ilGenerator.Emit(OpCodes.Ldc_I4_4);//ldc.i4.4 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(5); */ ilGenerator.Emit(OpCodes.Ldc_I4_5);//ldc.i4.5 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(6); */ ilGenerator.Emit(OpCodes.Ldc_I4_6);//ldc.i4.6 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(7); */ ilGenerator.Emit(OpCodes.Ldc_I4_7);//ldc.i4.7 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(8); */ ilGenerator.Emit(OpCodes.Ldc_I4_8);//ldc.i4.8 ilGenerator.Emit(OpCodes.Call, writeLineMethod); } static void Emit_Ldc_I4_S() { /* 生成 Console.WriteLine(-1); */ ilGenerator.Emit(OpCodes.Ldc_I4_S, (SByte)(-1));//ldc.i4.s -1 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(0); */ ilGenerator.Emit(OpCodes.Ldc_I4_S, 0);//ldc.i4.s 0 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(8); */ ilGenerator.Emit(OpCodes.Ldc_I4_S, 8);//ldc.i4.s 8 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(100); */ ilGenerator.Emit(OpCodes.Ldc_I4_S, 100);//ldc.i4.s 100 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(127); */ ilGenerator.Emit(OpCodes.Ldc_I4_S, 127);//ldc.i4.s 127 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(-128); */ ilGenerator.Emit(OpCodes.Ldc_I4_S, (SByte) (- 128));//ldc.i4.s -128 ilGenerator.Emit(OpCodes.Call, writeLineMethod); } static void Emit_Ldc_I4() { /* 生成 Console.WriteLine(-1); */ ilGenerator.Emit(OpCodes.Ldc_I4, -1);//ldc.i4 -1 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(0); */ ilGenerator.Emit(OpCodes.Ldc_I4, 0);//ldc.i4 0 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(8); */ ilGenerator.Emit(OpCodes.Ldc_I4, 8);//ldc.i4 8 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(-100); */ ilGenerator.Emit(OpCodes.Ldc_I4, -100);//ldc.i4 -100 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(127); */ ilGenerator.Emit(OpCodes.Ldc_I4, 127);//ldc.i4 127 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(-128); */ ilGenerator.Emit(OpCodes.Ldc_I4, (-128));//ldc.i4 -128 ilGenerator.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.WriteLine(2000); */ ilGenerator.Emit(OpCodes.Ldc_I4, 2000);//ldc.i4 2000 ilGenerator.Emit(OpCodes.Call, writeLineMethod); } public static void Generate() { InitAssembly(); /* 生成 public class LoadInt */ typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public); /* 生成 public static void Main() */ GenerateMain(); Emit_Ldc_I4_X(); Emit_Ldc_I4_S(); Emit_Ldc_I4(); EmitReadKey(); ilGenerator.Emit(OpCodes.Ret); /* 设置assembly入口方法 */ assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication); SaveAssembly(); Console.WriteLine("生成成功"); //Console.ReadKey(); } static void EmitReadKey() { /* 生成 Console.ReadKey(); */ MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { }); ilGenerator.Emit(OpCodes.Call, readKeyMethod); ilGenerator.Emit(OpCodes.Pop); } static void GenerateMain() { mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new Type[] { }); ilGenerator = mainMethod.GetILGenerator(); } static void InitAssembly() { AssemblyName assemblyName = new AssemblyName(namespaceName); assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName); } static void SaveAssembly() { Type t = typeBuilder.CreateType(); //完成Type,这是必须的 assemblyBuilder.Save(binaryName); } } }