数值的比较就是大于、小于、等于、大于等于、小于等于、不等于,它们的运算结果都是布尔值。
大于、小于、等于有直接对应的指令,分别是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. 分析了京东内衣销售记录,告诉你妹子们的真Size!

    >今天闲暇之余写了一个爬虫例子.通过爬虫去爬取京东的用户评价,通过分析爬取的数据能得到很多结果,比如,哪一种颜色的胸罩最受女性欢迎,以及中国女性的平均size(仅供参考哦~) 打开开发者工具-n ...

  2. ssm下的CURD

    https://github.com/MenghuiLiu/ssm-curd 以后有更新.... 照着前辈的足迹向前撸

  3. Linux基础之特殊权限

    22.5)特殊权限 22.5.1)SetUID(简称suid)(数字权限是4000) 命令功能: 临时使用命令的属主权限执行该命令.即如果文件有suid权限时,那么普通用户去执行该文件时,会以该文件的 ...

  4. Jquery 小结

    1. 名词解释 实例对象:var p1=new Person();  p1就是实例对象 构造:function Person(){} 原型对象:在 JavaScript 中,每当定义一个对象(函数也是 ...

  5. sort+结构体+简单数学+暴力-例题

    A-前m大的数 还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大 ...

  6. Vue事件修饰符详解

    整体学习Vue时看到Vue文档中有事件修饰符的描述,但是看了之后并没有理解是什么意思,于是查阅了资料,现在记录下来与大家分享 先给大家画一个示意图理解一下冒泡和捕获 (1) .stop修饰符 请看如下 ...

  7. Nginx安装(详细版本)

    Nginx安装文档 前言: 最近,系统部署人员那边,让我们给写一个傻瓜式的Nginx安装过程.所以就有了这个文档,本着独乐乐不如众乐乐,就分享一下.我觉得对入门小白来说,有图,乃至运行过程图,是很重要 ...

  8. iDevice取证的一大突破

    近日手机取证领域传出令人震撼的消息,知名取证大厂Cellebrite宣称可破解任何版本,任何机型的iDevice,连最新的iPhone X也逃不过. 若真属实,代表着iOS的取证又重现光明.只是不确定 ...

  9. xpath beautiful pyquery三种解析库

    这两天看了一下python常用的三种解析库,写篇随笔,整理一下思路.太菜了,若有错误的地方,欢迎大家随时指正.......(conme on.......) 爬取网页数据一般会经过 获取信息-> ...

  10. git的使用(一)

    git   —version  展示git的版本 tanya ~$ git --version git version 2.22.0 最小配置   git config —global user.na ...