zoukankan      html  css  js  c++  java
  • MSIL实用指南-比较运算


    数值的比较就是大于、小于、等于、大于等于、小于等于、不等于,它们的运算结果都是布尔值。
    大于、小于、等于有直接对应的指令,分别是Cgt、Clt、Ceq。
    大于等于、小于等于、不等于没有直接对应的指令,它的运算实现一般是取反。

    大于、小于、等于需要两个参数,它们的通用步骤
    1.生成加载左边变量
    2.生成加载右边变量
    3.生成比较运算指令

    生成等于比较的代码实例:

    ilGenerator.Emit(OpCodes.Ldarg_0);
    ilGenerator.Emit(OpCodes.Ldarg_1);
    ilGenerator.Emit(OpCodes.Ceq);


    下面以生成大于等于为例子,讲解一下怎么生成相应运算指令。
    前两个步骤还是生成加载左右参数。
    “生成等于”其实就是“不大于”,按顺序就是先比较是否是小于,然后把这个结果和false比较。
    IL指令中0代表false。
    即生成

    ilGenerator.Emit(OpCodes.Clt);
    ilGenerator.Emit(OpCodes.Ldc_I4_0);
    ilGenerator.Emit(OpCodes.Ceq);

    小于等于则是进行大于比较,然后再和0比较

    ilGenerator.Emit(OpCodes.Cgt);
    ilGenerator.Emit(OpCodes.Ldc_I4_0);
    ilGenerator.Emit(OpCodes.Ceq);

    不等于是先进行等于比较,然后看这个结果是否是false

    ilGenerator.Emit(OpCodes.Ceq);
    ilGenerator.Emit(OpCodes.Ldc_I4_0);
    ilGenerator.Emit(OpCodes.Ceq);

    上面可以看出,最后两条指令是固定的,都是和false比较,获得最终结果。

    完整的程序如下

    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace LX1_ILDemo
    {
        class Demo19_CompareOP
        {
            static string binaryName = "Demo19_CompareOP.exe";
            static string namespaceName = "LX1_ILDemo";
            static string typeName = "CompareOPDemo";
    
            static AssemblyBuilder assemblyBuilder;
            static ModuleBuilder moduleBuilder;
            static TypeBuilder typeBuilder;
            static MethodBuilder mainMethod;
            static MethodBuilder testMethod;
    
            static void Emit_Test()
            {
                testMethod = typeBuilder.DefineMethod("TestCompare", MethodAttributes.Public
                    | MethodAttributes.Static, typeof(void), new Type[] { typeof(int), typeof(int) });
                var println = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(bool) });
                var ilGenerator = testMethod.GetILGenerator();
                // >
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Ldarg_1);
                ilGenerator.Emit(OpCodes.Cgt);
                ilGenerator.Emit(OpCodes.Call, println);
    
                // < 
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Ldarg_1);
                ilGenerator.Emit(OpCodes.Clt);
                ilGenerator.Emit(OpCodes.Call, println);
    
                // ==
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Ldarg_1);
                ilGenerator.Emit(OpCodes.Ceq);
                ilGenerator.Emit(OpCodes.Call, println);
    
                //>=
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Ldarg_1);
                ilGenerator.Emit(OpCodes.Clt);
                ilGenerator.Emit(OpCodes.Ldc_I4_0);
                ilGenerator.Emit(OpCodes.Ceq);
                ilGenerator.Emit(OpCodes.Call, println);
    
                // <=
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Ldarg_1);
                ilGenerator.Emit(OpCodes.Cgt);
                ilGenerator.Emit(OpCodes.Ldc_I4_0);
                ilGenerator.Emit(OpCodes.Ceq);
                ilGenerator.Emit(OpCodes.Call, println);
    
                //!=
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Ldarg_1);
                ilGenerator.Emit(OpCodes.Ceq);
                ilGenerator.Emit(OpCodes.Ldc_I4_0);
                ilGenerator.Emit(OpCodes.Ceq);
                ilGenerator.Emit(OpCodes.Call, println);
    
                ilGenerator.Emit(OpCodes.Ret);
            }
    
            public static void Generate()
            {
                InitAssembly();
                typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public);
                Emit_Test();
                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_1);
                ilGenerator.Emit(OpCodes.Ldc_I4_7);
                ilGenerator.Emit(OpCodes.Call, testMethod);
    
                ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadKey", new Type[] { }));
                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
  • 相关阅读:
    android使用ant编译打包
    Android OpenGL ES 2.0 (二) 画立方体
    Android OpenGL ES 2.0 (三) 灯光pervertex lighting
    OpenGL ES2.0里的3种变量
    JAVA对DOM的一些解析、修改、新增操作
    webservice(二)示例代码
    linux改IP
    android从未安装的apk文件里获取信息(包信息,资源信息)
    Android OpenGL ES 2.0 (一) 画三角形
    一个关于closure的问题.
  • 原文地址:https://www.cnblogs.com/tkt2016/p/8708821.html
Copyright © 2011-2022 走看看