MSIL实用指南-加载null、string、long、float、double等值
本篇讲述怎么加载null、string值、long值、float值、double值。
加载null不需要参数值,只要
Emit ldnull
其它几个命令要
Emit <指令> <值>
加载null
加载null是很简单的,使用OpCodes.Ldnull,以下一句程序就可以了。
ilGenerator.Emit(OpCodes.Ldnull);
加载string值
加载string值也很简单,使用OpCodes.Ldstr,格式是
ilGenerator.Emit(OpCodes.Ldstr, <string值>);
比如
ilGenerator.Emit(OpCodes.Ldstr, "hello...");
加载long值
使用格式OpCodes.Ldc_I8指令,是ilGenerator.Emit(OpCodes.Ldc_I8, <long值>);
比如
ilGenerator.Emit(OpCodes.Ldc_I8, long.MaxValue);
需要注意的是,下面这一句是有问题的,120默认是int型,不是long型,生成的指令是没法正确运行的。
ilGenerator.Emit(OpCodes.Ldc_I8, 120);
必须加long强制转换,修正为
ilGenerator.Emit(OpCodes.Ldc_I8, (long)120);
加载float值
使用格式OpCodes.Ldc_R4指令,格式是ilGenerator.Emit(OpCodes.Ldc_R4, <float值>);
比如
ilGenerator.Emit(OpCodes.Ldc_R4, float.MinValue)
也要注意的,下面这一句有问题,5.5默认是dobule型,不是float型,生成的指令也不能正确运行的。
ilGenerator.Emit(OpCodes.Ldc_R4, 5.5);
必须加long强制转换,修正为
ilGenerator.Emit(OpCodes.Ldc_R4, (float)5.5);
加载double值
使用格式OpCodes.Ldc_R8指令,格式是ilGenerator.Emit(OpCodes.Ldc_R4, <double值>);
比如
ilGenerator.Emit(OpCodes.Ldc_R8, (double)6.5);
完整的程序如下:
using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
/// <summary>
/// load null、string值、long值、float值、double值、
/// </summary>
class Demo02_LoadLFDSN
{
static string binaryName = "Demo02_LoadLFDSN.exe";
static string namespaceName = "LX1_ILDemo";
static string typeName = "LoadLFDSN"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder;
static MethodBuilder mainMethod;
static ILGenerator ilGenerator; static void Emit_Ldc()
{
/* 加载string值的Ldstr指令使用 */
MethodInfo writeStringLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); /* 加载null的Ldnull指令使用 */
ilGenerator.Emit(OpCodes.Ldnull);//ldnull
ilGenerator.Emit(OpCodes.Call, writeStringLineMethod); /* 加载string的Ldstr指令使用 */
ilGenerator.Emit(OpCodes.Ldstr, "hello...");//ldstr "hello..."
ilGenerator.Emit(OpCodes.Call, writeStringLineMethod); /* 加载long值的Ldc_I8指令使用 */
MethodInfo writeLongLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(long) });
ilGenerator.Emit(OpCodes.Ldc_I8, (long));//数值前面的强制转换‘(long)’是必须的,默认会把‘120’作为int,导致生成的程序运行错误
ilGenerator.Emit(OpCodes.Call, writeLongLineMethod);
ilGenerator.Emit(OpCodes.Ldc_I8, long.MaxValue);//ldc.i8 0x7fffffffffffffff
ilGenerator.Emit(OpCodes.Call, writeLongLineMethod);
ilGenerator.Emit(OpCodes.Ldc_I8, long.MinValue);//ldc.i8 0x8000000000000000
ilGenerator.Emit(OpCodes.Call, writeLongLineMethod); /* 加载float值的Ldc_R4指令使用 */
MethodInfo writeFloatLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(float) });
ilGenerator.Emit(OpCodes.Ldc_R4, (float)5.5);//数值前面的强制转换‘(float)’是必须的,默认会把‘5.5’作为double,导致生成的程序运行错误
ilGenerator.Emit(OpCodes.Call, writeFloatLineMethod);
ilGenerator.Emit(OpCodes.Ldc_R4, float.MaxValue);//ldc.r4 3.4028235e+038
ilGenerator.Emit(OpCodes.Call, writeFloatLineMethod);
ilGenerator.Emit(OpCodes.Ldc_R4, float.MinValue);//ldc.r4 -3.4028235e+038
ilGenerator.Emit(OpCodes.Call, writeFloatLineMethod); /* 加载double值的Ldc_R8指令使用 */
MethodInfo writeDoubleLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(double) });
ilGenerator.Emit(OpCodes.Ldc_R8, (double)6.5);//ldc.r8 6.5
ilGenerator.Emit(OpCodes.Call, writeDoubleLineMethod);
ilGenerator.Emit(OpCodes.Ldc_R8, double.MaxValue);//ldc.r8 1.7976931348623157e+308
ilGenerator.Emit(OpCodes.Call, writeDoubleLineMethod);
ilGenerator.Emit(OpCodes.Ldc_R8, double.MinValue);//ldc.r8 -1.7976931348623157e+308
ilGenerator.Emit(OpCodes.Call, writeDoubleLineMethod);
} public static void Generate()
{
InitAssembly(); /* 生成 public class LoadLFDSN */
typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public); /* 生成 public static void Main() */
GenerateMain(); Emit_Ldc(); EmitReadKey();
ilGenerator.Emit(OpCodes.Ret); /* 设置assembly入口方法 */
assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication); SaveAssembly();
Console.WriteLine("生成成功");
//Console.ReadKey();
} static void EmitReadKey()
{
/* 生成 Console.ReadKey(); */
MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
ilGenerator.Emit(OpCodes.Call, readKeyMethod);
ilGenerator.Emit(OpCodes.Pop);
} static void GenerateMain()
{
mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new Type[] { });
ilGenerator = mainMethod.GetILGenerator();
} 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实用指南-加载null、string、long、float、double等值的更多相关文章
- MSIL实用指南-加载bool、sbyte、byte、char、short等值
这一篇讲解怎么加载bool值.sbyte值.byte值.char值.short值. 加载bool值在.NET程序实际运行中,是没有true和false值的,实际上是以1和0表示它们,加载它们的指令是L ...
- MSIL实用指南-加载和保存参数
本篇讲解怎么加载和保存参数,以及参数起始序号的确定. 参数的加载加载参数的指令是Ldarg.Ldarg_S.Ldarg_0.Ldarg_1.Ldarg_2.Ldarg_3.Ldarg_0是加载第0个参 ...
- MSIL实用指南-加载int值
这一篇讲的是怎样加载整数值到运算栈上.这一类的指令都是以Ldc_I4开头. Ldc_I4类OpCodes的Ldc_I4字段的功能是把一个int值压入运算栈上.它的使用方法是ilGenerator.Em ...
- MSIL实用指南-Action的生成和调用
MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...
- MSIL实用指南-生成索引器
MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...
- MSIL实用指南-字段的加载和保存
字段有静态字段和非静态字段之分,它们的加载保存指令也是不一样的,并且非静态字段要生成this. 静态字段的加载加载静态字段的指令是Ldsfld.ilGenerator.Emit(OpCodes.Lds ...
- MSIL实用指南-局部变量的声明、保存和加载
这一篇讲解方法内的局部变量是怎么声明.怎样保存.怎样加载的. 声明局部变量声明用ILGenerator的DeclareLocal方法,参数是局部变量的数据类型,得到一个局部变量对应的创建类LocalB ...
- MSIL实用指南-一维数组的操作
本篇讲解怎么生成和操作一维数组.各种数组类型创建的步骤是一样的,但是加载和保存步骤有所不同. 一.创建数组所有类型的一维数组创建都是一样的,分三步.1.加载数组长度2.生成指令 Newarr < ...
- MSIL实用指南-生成foreach语句
foreach可以迭代数组或者一个集合对象.foreach语句格式是它的生成步骤是foreach (<成员> in <集合>) <循环体> 一.声明三个变量,loc ...
随机推荐
- egametang启动配置
egametang的启动配置文件可以在Unity的Tools->命令行配置中修改保存然后启动 如果需要添加自定义的启动配置项目,只需要修改客户端的 ServerCommandLineEditor ...
- [求助][SPOJ MARIOGAM]-高斯消元(内含标程,数据等)
小蒟蒻开始做概率的题之后,遇到了这道题,然而,他发现自己的程序调试了无数次也无法通过,系统总是返回令人伤心的WA, 于是,他决定把这一天半的时间收集到的资料放在网上, 寻求大家的帮助, 也可以节省后来 ...
- linux 下yum使用技巧
本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 经常会遇上一些linux系统允许你上外网,而一些是不允许的,这时我们 ...
- bzoj 1814 Ural 1519 Formula 1 插头DP
1814: Ural 1519 Formula 1 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 942 Solved: 356[Submit][Sta ...
- MysqL_SELECT FOR UPDATE详解
先来举一个在某些应用场景下会出现数据不一致的例子,当然存储引擎是InnoDB(至于为什么,后面再告诉你). 电商平台常见的下单场景: 一般商品表(goods)有基本的四个字段,id(主键),goods ...
- Python基于Flask框架配置依赖包信息的项目迁移部署小技巧
一般在本机上完成基于Flask框架的代码编写后,如果有接口或者数据操作方面需求需要把代码部署到指定服务器上. 一般情况下,使用Flask框架开发者大多数都是选择Python虚拟环境来运行项目,不同的虚 ...
- JVM笔记5-对象的访问定位。
java虚拟机中指定一个栈内存的引用指向了堆内存中的对象.这样说只是笼统的说法.而指向堆内存中的对象就一定是栈引用所需要的那个对象吗?其实并不定. 这就需要知道对象的访问定位方式有两种: 1.使用句柄 ...
- java 集合框架(一)概述
一.概述 Java Collection Framework (JCF) 提供给我们一系列的类和接口,方便开发者处理集合对象. 在Java 2之前,Java是没有完整的集合框架的.它只有一些简单的可以 ...
- php学习笔记位运算
位运算 源码:用二进制表示一个数,这个码就是源码. 比如2====00000000 00000000 0000000 00000010 正数的反码 源码 补码都一样 负数的源码是符号位取反.第一个位 ...
- Maximum Entropy Model(最大熵模型)初理解
0,熵的描述 熵(entropy)指的是体系的混沌的程度(可也理解为一个随机变量的不确定性),它在控制论.概率论.数论.天体物理.生命科学等领域都有重要应用,在不同的学科中也有引申出的更为具体的定义, ...