本篇讲述怎么加载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 ...
随机推荐
-
Visual Studio 2015上安装Entity Framework Power Tools
Entity Framework Power Tools是个非常好用的EF Code First插件.通过它能够非常简单地生成和数据库结构匹配的model和dbcontext代码.使用的方法,这里有介 ...
-
显示SQL Server分配的全部内存
1.在sqlserver 中建立查询 2.执行 DBCC MEMORYSTATUS 在Windows Server 2000/2003任务管理器中,“内存使用”这个字段是显示工作区分配的内存.一个进程 ...
-
css居中学习笔记
css居中学习笔记 一.水平居中 以下面的代码为例: <body> <div class="parent"> <div class="chi ...
-
关于java的转义字符
关于java的转义字符 我们都知道 String s="ad,dfjdlfs,df,s,dfl"; 执行 String re[]=s.split(&qu ...
-
spring-boot 整合redis作为数据缓存
添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp ...
-
国内大学毕业论文LaTeX模板集合
国内大学毕业论文LaTeX模板集合 薛瑞尼的清华大学学位论文LaTeX模板http://sourceforge.net/projects/thuthesis/ 北大论文文档 LaTeX 模板 pkut ...
-
冲刺NO.6
Alpha冲刺第六天 站立式会议 项目进展 项目中学生基本信息管理,与系统管理员模块基本完成,团队开始编写学生信用信息模块内容与奖惩事务管理内容,准备开始对已完成模块进行测试. 问题困难 团队成员对前 ...
-
angularjs知识点
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
-
CEF 支持的命令行参数
参考:https://peter.sh/experiments/chromium-command-line-switches/ List of Chromium Command Line Switch ...
-
idea appliction context not configured for this file
File --> Project Structure