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);
}
}
}
MSIL实用指南-比较运算的更多相关文章
- MSIL实用指南-位运算
C#支持的位运算是与.或.异或.取反.左移.右移,它们对应的指令是And.Or.Xor.Not.Shl.Shr. 取反运算只需要一个操作数,生成步骤是1.生成加载变量2.生成取反指令实例代码: ilG ...
- MSIL实用指南-数学运算
C#支持的数学运算是加.减.乘.除.取模,它们对应的指令是Add.Sub.Mul.Div.Rem. 这五个运算都需要两个参数,它们的通用步骤1.生成加载左边变量2.生成加载右边变量3.生成运算指令 实 ...
- MSIL实用指南-生成索引器
MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...
- MSIL实用指南-Action的生成和调用
MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...
- MSIL实用指南-局部变量的声明、保存和加载
这一篇讲解方法内的局部变量是怎么声明.怎样保存.怎样加载的. 声明局部变量声明用ILGenerator的DeclareLocal方法,参数是局部变量的数据类型,得到一个局部变量对应的创建类LocalB ...
- MSIL实用指南-逻辑运算
逻辑运算有三种:与.或.非.实现它们可以用位运算指令And.Or.Not等三个指令.它们的使用方法和位运算一致. 完整的程序如下: using System; using System.Reflect ...
- MSIL实用指南-加载int值
这一篇讲的是怎样加载整数值到运算栈上.这一类的指令都是以Ldc_I4开头. Ldc_I4类OpCodes的Ldc_I4字段的功能是把一个int值压入运算栈上.它的使用方法是ilGenerator.Em ...
- MSIL实用指南-IL版hello world
我们学习编程开始时,一般用输出"hello world"的一段程序. C#版的"hello world"是 using System; namespace L0 ...
- MSIL实用指南-加载null、string、long、float、double等值
本篇讲述怎么加载null.string值.long值.float值.double值. 加载null不需要参数值,只要 Emit ldnull 其它几个命令要 Emit <指令> <值 ...
随机推荐
- MySQL常用工具、日志及读写分离
MySQL常用工具.日志及读写分离 1.MySQL中常用工具 1.1 mysql 1.1.1连接选项 1.1.2 执行选项 1.2 mysqladmin 1.3 mysqlbinlog 1.4 mys ...
- JQuery第一章js 上机+课后
=============上机1 包含字母 <!DOCTYPE html> <html> <head> <title>sj1.html& ...
- bootstrap开发响应式网页的常用的一些 类的说明
1.navbar-导航条 1.navbar-fixed-top,让导航条固定显示在页面上部(注意:固定的导航条会遮住代码,解决方案,给body设置padding-top的值[大于或等于]为我们导航条的 ...
- GDB 基本用法
1.编译文件时需要加上 -g 选项,并非是将源码嵌入可执行文件,只是加入源代码的信息.eg:gcc -g main.c -o main 2.直接按回车键会重复上一条命令 3.基本指令 help,可以查 ...
- kubeadm源码分析
k8s离线安装包 三步安装,简单到难以置信 kubeadm源码分析 说句实在话,kubeadm的代码写的真心一般,质量不是很高. 几个关键点来先说一下kubeadm干的几个核心的事: kubeadm ...
- 用html和css写一个头部header和左侧菜单栏menu-bar固定的的页面
这个页面header部分是100%的宽度,60px的高度,左侧是刚好一屏的高度,180的宽度,右侧的部分把剩余的空间占满,刚开始的时候还没怎么接触这样的页面,以为使用js读取浏览的可视化宽高,然后在做 ...
- maven 打包并导出 lib 第三方jar
一. maven 导出lib 包 执行命令 mvn dependency:copy-dependencies -DoutputDirectory=target/lib 或者在 eclipse 中执行, ...
- ThreadLocal线程隔离
package com.cookie.test; import java.util.concurrent.atomic.AtomicInteger; /** * author : cxq * Date ...
- Ubuntu 16.04 安装 SVN-Client (RaabitVCS)
1.添加源 sudo add-apt-repository ppa:rabbitvcs/ppa 2. 更新源 sudo apt-get update 3.安装依赖库 sudo apt-get inst ...
- 用友java后端开发面经
面的是深圳的友金锁 3月28号 早上十点 之前来学校宣讲加笔试(笔试做的很菜) 以为凉了,27号被捞起来了,现在看来面了也有点凉 视频面试 时间:19分钟左右 面试官人不错 1 自我介绍 2 自我介绍 ...