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 ...
随机推荐
- angular2^ typescript 将 文件和Json数据 合并发送到服务器(1.客户端处理)
首先介绍下框架基本流程 (web > webservice [前端架构] ) > (nodejs [ 数据中转站 ]) >(api [后台接口]) --web (html a ...
- CSS布局(一) 盒子模型
一.盒子模型 标准盒子模型 从下图可以看到标准 w3c 盒子模型的范围包括 content.padding.border.margin,并且 content 部分不包含其他部分. 怪异盒子模型 从下图 ...
- Python3实现QQ机器人自动爬取百度文库的搜索结果并发送给好友(主要是爬虫)
一.效果如下: 二.运行环境: win10系统:python3:PyCharm 三.QQ机器人用的是qqbot模块 用pip安装命令是: pip install qqbot (前提需要有request ...
- B站标题/子标题/url爬取示例(requests+re)
#coding:utf-8 __author__ = "zhoumi" 3 import requests import re import urllib ''' 本文档目的在于获 ...
- unbuntu 系统登录华南师范大学校园网的方法
最近刚装了unbuntu 系统,刚开始网络连接遇到了点小问题,原来是校园网不知道怎么认证,于是向好基友请教了下,得出快捷的方法如下: 下载学校网络的认证客户端,记住位置,一般都是默认下载地址是 Dow ...
- 小技巧:selenium java中如何使用chrome默认的profile
使用浏览器默认的profile可以在一定程度上实现免登录的效果,另外默认的profile中很多文件都被缓存了,也有利于加快测试的速度 System.setProperty("webdrive ...
- .NET Core阿里大于短信发送SDK修改以及使用
一.问题背景 继上次七牛云SDK的问题之后(参考:http://www.cnblogs.com/OMango/p/8447480.html),在发送短信的功能上又出现了问题,我们短信服务使用的是阿里大 ...
- spring boot admin + spring boot actuator + erueka 微服务监控
关于spring boot actuator简单使用,请看 简单的spring boot actuator 使用,点击这里 spring boot admin 最新的正式版本是1.5.3 与 spri ...
- nginx笔记2-负载均衡
负载均衡实现方式分为两类:1硬件类,2软件类. 硬件类:F5(这是一种硬件,并不是刷新啊,不要误解) 优点:非常快,可靠性高,并发量大.缺点:太贵,成本高,不方便,最致命的是不能将动态请求和静态请求 ...
- HashPayloadPcapReader
package net.ripe.hadoop.pcap; import java.io.DataInputStream; import java.io.IOException; import com ...