• 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
  • 相关阅读:
    react_瞎敲
    linux 删除类似文件
    mysql建立dblink 视图,无法查询到数据的问题
    Guava-Retrying 请求重试机制
    Command line is too long. Shorten command line for WebServiceUtilsTest.callMethod or also for JUnit default
    @Scheduled 定时任务注解不能运行
    jq拷贝表单$("#searchForm").clone(true),无法将select2数据value拷贝的问题
    正则表达式的lookaround(lookahead/lookbehind)以及密码复杂度检查
    MYSQL列的长度,NUMERIC_PRECISION和COLUMN_TYPE
    Qira-docker安装与使用
  • 原文地址:https://www.cnblogs.com/tkt2016/p/8778814.html
Copyright © 2020-2023  润新知