数值的比较就是大于、小于、等于、大于等于、小于等于、不等于,它们的运算结果都是布尔值。
大于、小于、等于有直接对应的指令,分别是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);
}
}
}

MSIL实用指南-比较运算的更多相关文章

  1. MSIL实用指南-位运算

    C#支持的位运算是与.或.异或.取反.左移.右移,它们对应的指令是And.Or.Xor.Not.Shl.Shr. 取反运算只需要一个操作数,生成步骤是1.生成加载变量2.生成取反指令实例代码: ilG ...

  2. MSIL实用指南-数学运算

    C#支持的数学运算是加.减.乘.除.取模,它们对应的指令是Add.Sub.Mul.Div.Rem. 这五个运算都需要两个参数,它们的通用步骤1.生成加载左边变量2.生成加载右边变量3.生成运算指令 实 ...

  3. MSIL实用指南-生成索引器

    MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...

  4. MSIL实用指南-Action的生成和调用

    MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...

  5. MSIL实用指南-局部变量的声明、保存和加载

    这一篇讲解方法内的局部变量是怎么声明.怎样保存.怎样加载的. 声明局部变量声明用ILGenerator的DeclareLocal方法,参数是局部变量的数据类型,得到一个局部变量对应的创建类LocalB ...

  6. MSIL实用指南-逻辑运算

    逻辑运算有三种:与.或.非.实现它们可以用位运算指令And.Or.Not等三个指令.它们的使用方法和位运算一致. 完整的程序如下: using System; using System.Reflect ...

  7. MSIL实用指南-加载int值

    这一篇讲的是怎样加载整数值到运算栈上.这一类的指令都是以Ldc_I4开头. Ldc_I4类OpCodes的Ldc_I4字段的功能是把一个int值压入运算栈上.它的使用方法是ilGenerator.Em ...

  8. MSIL实用指南-IL版hello world

    我们学习编程开始时,一般用输出"hello world"的一段程序. C#版的"hello world"是 using System; namespace L0 ...

  9. MSIL实用指南-加载null、string、long、float、double等值

    本篇讲述怎么加载null.string值.long值.float值.double值. 加载null不需要参数值,只要 Emit ldnull 其它几个命令要 Emit <指令> <值 ...

随机推荐

  1. IIS身份验证和文件操作权限(一、身份验证配置)

    最近有一个项目服务器需要升级,主要是Web项目.因为以前是只写代码,不管发布.所以在环境构筑方面就出现自己的知识盲点.盲点一:IIS的身份验证的作用盲点二:IIS的身份验证和文件操作权限的关系(重点) ...

  2. windows上node开发注意事项

    windows上进行node.react开发的必要步骤: 1.使用nvm进行node及npm包管理工具,记得使用npm config set ...:2.另外react仅支持python3.0以下的版 ...

  3. Python之父新发文,将替换现有解析器

    花下猫语: Guido van Rossum 是 Python 的创造者,虽然他现在放弃了"终身仁慈独裁者"的职位,但却成为了指导委员会的五位成员之一,其一举一动依然备受瞩目.近日 ...

  4. selenium Java中常见等待的几种形式

    前言 在自动化测试中,我们经常会碰到编写脚本过程中操作某个元素的时候, 需要等待页面加载完成后,才能对元素操作,否则会报错,提示页面元素不存在异常,我们需要等待元素加载完成后,才能继续操作,而Sele ...

  5. handlerAdapter与方法返回值的处理

    前提:处理器方法被调用并返回了结果 public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer ma ...

  6. TCP加速机制是如何加速的?

    一.什么是TCP加速?   TCP加速就是在高时延链路提高吞吐量的一系列解决方案.   二.为什么需要对TCP进行加速?   1.传统的TCP拥塞控制算法并不适用于高时延.高误码的链路. 2.随着we ...

  7. Restful API 中的错误处理

    简介 随着移动开发和前端开发的崛起,越来越多的 Web 后端应用都倾向于实现 Restful API. Restful API 是一个简单易用的前后端分离方案,它只需要对客户端请求进行处理,然后返回结 ...

  8. 【C++】string::substr函数

    形式:s.substr(p, n) 返回一个string,包含字符串s中从p开始的n个字符的拷贝(p的默认值是0,n的默认值是s.size() - p,即不加参数会默认拷贝整个s) int main( ...

  9. linux安装启动mongodb

    1:下载 http://www.mongodb.org/downloads 在85机器上上传压缩包后解压缩. 首先在linux中解压缩安装程序 通过命令操作: 解压 tar -zxvf mongodb ...

  10. 发布一个自己的jar包给全球人使用

    目录 项目准备 sonatype 注册 申请sonatype工单 gpg配置 项目配置 依赖oss-parent 自定义配置 pom配置 全局settings配置 发布 验证 maven 项目对于我们 ...