MSIL实用指南-生成while语句


本篇讲解怎样生成while语句。while语句是编程语言中很重要的循环语句,它的结构是
while(<表达式>)
<语句或语句块>

当表达式的结果为true时就一直执行语句或语句块,否则就结束执行循环。
while语句的生成步骤是这样的。

一、声明两个跳转标签
while只需要两个跳转标签,分别用在表示式指令之前和语句块指令之前。

二、生成无条件跳转到表达式开始标签的指令
这是固定的,只有一句话。

三、标记语句块开始标签位置

四、并且生成语句块指令

五、标记表达式开始标签位置

六、并且生成表达式指令

七、生成Brtrue_S跳转到语句块开始标签的指令


完整程序如下:

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace LX1_ILDemo
{
    class Demo25_While
    {
        static string binaryName = "Demo25_While.exe";
        static string namespaceName = "LX1_ILDemo";
        static string typeName = "DemoWhile";

        static AssemblyBuilder assemblyBuilder;
        static ModuleBuilder moduleBuilder;
        static TypeBuilder typeBuilder;
        static MethodBuilder mainMethod;
        static MethodBuilder testMethod;

        static void Emit_TestMethod()
        {
            testMethod = typeBuilder.DefineMethod("Test", MethodAttributes.Public
               | MethodAttributes.Static, typeof(void), new Type[] { typeof(int)});
            ILGenerator ilGenerator = testMethod.GetILGenerator();

            Label labelConditionStart = ilGenerator.DefineLabel();
            Label labelBlockSart = ilGenerator.DefineLabel();
            MethodInfo writeIntLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });

            ilGenerator.Emit(OpCodes.Br_S, labelConditionStart);

            ilGenerator.MarkLabel(labelBlockSart);
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Call, writeIntLineMethod);
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldc_I4_1);
            ilGenerator.Emit(OpCodes.Sub);
            ilGenerator.Emit(OpCodes.Starg_S, 0);

            ilGenerator.MarkLabel(labelConditionStart);
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldc_I4_0);
            ilGenerator.Emit(OpCodes.Cgt);

            ilGenerator.Emit(OpCodes.Brtrue_S, labelBlockSart);

            ilGenerator.Emit(OpCodes.Ret);
        }
         
        public static void Generate()
        {
            InitAssembly();
            typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public);

            Emit_TestMethod();
            GenerateMain();

            assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
            SaveAssembly();
            Console.WriteLine("生成成功");
        }

        static void GenerateMain()
        {
            mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
                | MethodAttributes.Static, typeof(void), new Type[] { });
            var ilGenerator = mainMethod.GetILGenerator();
            ilGenerator.Emit(OpCodes.Ldc_I4_S,(sbyte)10);
            ilGenerator.Emit(OpCodes.Call, testMethod);
     
            MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
            ilGenerator.Emit(OpCodes.Call, readKeyMethod);
            ilGenerator.Emit(OpCodes.Pop);

            ilGenerator.Emit(OpCodes.Ret);
        }

        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);
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/tkt2016/p/8778814.html