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 ...
随机推荐
- grep命令的-P选项
man grep的时候有一个-P,文档上的英文: -P, --perl-regexp Interpret PATTERN as a Perl regular expression. This is ...
- Scrapy-简单介绍
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 其最初是为了 页面抓取 (更确切来说, 网络抓取 )所设计的, ...
- SpringCloud入门1-服务注册与发现(Eureka)
前言 Oracle转让Java,各种动态语言的曝光率上升,Java工程师的未来在哪里?我觉得Spring Cloud让未来有无限可能.拖了半年之久的Spring Cloud学习就从今天开始了.中文教材 ...
- 从零开始学习前端JAVASCRIPT — 14、闭包与继承
一.闭包 1 . 概念:闭包就是能够读取其他函数内部变量的函数.在JS中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解为”定义在一个函数内部的函数”. 2 . 闭包的特点 1)可以读取 ...
- eclipse快捷键及设置
1.Eclipse设置新建菜单初始项 windows-->Perspective-->Customize Perspective--> 2.Eclipse快捷键 1. ctrl+sh ...
- Linux CentOS7下安装python3
在CentOS7下,默认安装的就是python2.7,我现在来教大家如何安装python3: 1.首先安装python3.6可能使用的依赖 # yum -y install openssl-devel ...
- linux系统/sbin/init执行过程
对于Linux的启动过程,之前一直都是研究到内核运行/sbin/init,启动第一个用户进程为止,因为这部分一直都是在内核态工作,所以对于学习内核还是有帮助的,当时/sbin/init之后的过程也需要 ...
- U-boot-1.1.4中关于hello_world.srec出错
make[1]: *** No rule to make target `hello_world.srec', needed by `all'. Stop. make[1]: Leaving dir ...
- 2.4 PCI总线的配置
PCI总线定义了两类配置请求,一个是Type 00h配置请求,另一个是Type 01h配置请求.PCI总线使用这些配置请求访问PCI总线树上的设备配置空间,包括PCI桥和PCI Agent设备的配置空 ...
- mysql常用基础操作语法(七)--统计函数和分组查询【命令行模式】
注:文中所有的...代表多个. 1.使用count统计条数:select count(字段名...) from tablename; 2.使用avg计算字段的平均值:select avg(字段名) f ...