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
转载于:https://www.cnblogs.com/tkt2016/p/8708821.html
MSIL实用指南-比较运算相关推荐
- MSIL实用指南-返回结果
一个方法体执行完指令后,必须要完成调用并返回,这是要使用Ret指令. Ret指令的详细解释是从当前方法返回,并将返回值(如果存在)从被调用方的计算堆栈推送到调用方的计算堆栈上.就是说如果计算堆栈上没有 ...
- MSIL实用指南-生成break和continue
break和continue本质都是标签的跳转 转载于:https://www.cnblogs.com/tkt2016/p/8807420.html
- MSIL实用指南-加载和保存参数
本篇讲解怎么加载和保存参数,以及参数起始序号的确定. 参数的加载 加载参数的指令是Ldarg.Ldarg_S.Ldarg_0.Ldarg_1.Ldarg_2.Ldarg_3. Ldarg_0是加载第0 ...
- 《Scikit-Learn与TensorFlow机器学习实用指南》第4章 训练模型
第4章 训练模型 来源:ApacheCN<Sklearn 与 TensorFlow 机器学习实用指南>翻译项目 译者:@C-PIG 校对:@PeterHo @飞龙 在之前的描述中,我们通常 ...
- ann matlab,MatlabANN工具箱实用指南.doc
MatlabANN工具箱实用指南 Matlab的神经网络工具箱实用指南 文章摘要:第一章是神经网络的基本介绍,第二章包括了由工具箱指定的有关网络结构和符号的基本材料以及建立神经网络的一些基本函数,例如 ...
- Python 无监督学习实用指南:1~5
原文:Hands-on unsupervised learning with Python 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自[ApacheCN 深度学习 译文集],采用译后编 ...
- Fedora和Red Hat Enterprise Linux实用指南(第6版)(上、下册)( 入行必读的Linux圣经)
Fedora和Red Hat Enterprise Linux实用指南(第6版)(上.下册)( 入行必读的Linux圣经) (美)苏贝尔(SobellL,M.G.)著 李洋等译 ISBN 978-7- ...
- Python 无监督学习实用指南:6~10
原文:Hands-on unsupervised learning with Python 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自[ApacheCN 深度学习 译文集],采用译后编 ...
- WPF实用指南二:移除窗体的图标
原文:WPF实用指南二:移除窗体的图标 WPF没有提供任何功能来移除窗体上的icon图标.一般的做法是设置一个空白的图标,如下图1: 这种做法在窗体边框与标题之间仍然会保留一片空白. 比较好的做法是使 ...
最新文章
- 219个opencv常用函数汇总
- 使用BH1750测量激光发射器的强度
- __clone class php_PHP 对象克隆 clone 关键字与 __clone() 方法
- C#模拟MSN窗体抖动
- 【资讯】2017年最好的25大发明,你最钟爱哪个?
- 数据 3 分钟 | 多家数据库厂商联合发布《分布式数据库发展路径研究》报告、巨杉数据库公布 2021 春季发布会时间...
- 微积分经典概念:极限、连续与函数
- win10 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建
- WCF开发之消息契约(MessageContract)
- websocket 如何知道对方断开_在爱情里你知道该如何和对方相处吗?
- c语言中strncpy的用法,C语言中函数strcpy ,strncpy ,strlcpy的用法【转】
- 客车网上售票系统(Java源码+sql脚本)
- SprngBoot引用外部jar包和本身日志接口冲突问题解决办法
- 5047. 多边形三角剖分的最低得分
- 全国二级计算机考试准考证打印官网
- iOS播放器之基于VLCKit的自定义播放器
- .pdm文件怎么打开
- 请你谈谈为什么分布式系统需要限流器
- NSA/SA手机都是真5G 用户已购5G手机不受明年政策影响
- 裁员10%,涉万人!Tesla这次“玩”大了…