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 ...
随机推荐
- C# 快速高效率复制对象的几种方式
http://www.cnblogs.com/emrys5/p/expression_trans_model.html 这篇较具体. 本文基于上文略加改动,暂记 using Newtonsoft.Js ...
- 关于c++栈溢出的问题
我自己定义了一个数据类型node,嵌套在另一个数据类型当中时候,用到了delete函数, 在我node的声明当中声明了几个指针 在我的析构函数中却调用了delet函数 结果程序结果是能跑出来 提示我栈 ...
- 初学Python(第一课)
今天整理一下关于Python初学者的基础知识部分的第一课,因为之前学习过C,所以过于基础的知识就不详细记录了. Python相对于C\C++来说,在语法方面已经很简单了:甚至对于JavaScript也 ...
- OpenCV 之 空间滤波
1 空间滤波 1.1 基本概念 空间域,在图像处理中,指的是像平面本身: 空间滤波,则是在像平面内,对像素值所进行的滤波处理. 如上图所示,假设点 (x, y) 为图像 f 中的任意点,中间正方形 ...
- (转载)SVM-基础(一)
支持向量机: Maximum Margin Classifier by pluskid, on 2010-09-08, in Machine Learning 87 comments 本文是 ...
- [Note] Apache Flink 的数据流编程模型
Apache Flink 的数据流编程模型 抽象层次 Flink 为开发流式应用和批式应用设计了不同的抽象层次 状态化的流 抽象层次的最底层是状态化的流,它通过 ProcessFunction 嵌入到 ...
- 【开源项目】智能电视及电视盒子的控制应用TVRemoteIME的接口说明
一.APP项目介绍: APP名称:TVRemoteIME 功能说明:安卓智能电视或者安卓盒子的控制应用,可跨屏远程输入.远程遥控(代替遥控器)盒子.盒子应用及文件管理.HTTP/RTMP/MMS网络视 ...
- Shell——数学计算
shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法,以后用到的时候可以来看,呵呵1.错误方法举例 a) var=1+1 echo $var 输出的结果是1+1, ...
- openstack-ocata-计算服务4
一. 计算服务概览 使用OpenStack计算服务来托管和管理云计算系统.OpenStack计算服务是基础设施即服务(IaaS)系统的主要部分,模块主要由Python实现. OpenStack计算组件 ...
- 【Unity3D】Unity3D开发《我的世界》之五、创建无限地形(视频)
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/unity_minecraft_05.html 一.导入Unity3D自带的第一人称角色控制器 直接导入就行,我们用 ...