MSIL实用指南-局部变量的声明、保存和加载
这一篇讲解方法内的局部变量是怎么声明、怎样保存、怎样加载的。
声明局部变量
声明用ILGenerator的DeclareLocal方法,参数是局部变量的数据类型,得到一个局部变量对应的创建类LocalBuilder。
使用格式是
LocalBuilder localBuilderx = ilGenerator.DeclareLocal(typeof(<数据类型>));
实际例子
LocalBuilder localBuilderv1 = ilGenerator.DeclareLocal(typeof(string));//声明一个string类型局部变量
LocalBuilder localBuilderv2 = ilGenerator.DeclareLocal(typeof(int));//声明一个int类型局部变量
LocalBuilder对象有两个重要的属性LocalType和LocalIndex。
属性LocalType的数据类型是System.Type,它表示的是这个局部变量的数据类型。
属性LocalIndex是int类型,它表示的是这个局部变量在这个方法体内的局部变量索引,并且是从0 开始的;假如这个局
部变量所在方法体的ilGenerator第n次调用DeclareLocal方法,那么它的LocalIndex就是(n-1)。
保存局部变量
保存局部变量的指令是Stloc、Stloc_S、Stloc_0、Stloc_1、Stloc_2、Stloc_3。
Stloc是通用指令;
当LocalBuilder的LocalIndex在0到255之间时,推荐用Stloc_S;
当LocalBuilder的LocalIndex为0时,推荐用Stloc_0;
当LocalBuilder的LocalIndex为1时,推荐用Stloc_1;
当LocalBuilder的LocalIndex为2时,推荐用Stloc_2;
当LocalBuilder的LocalIndex为3时,推荐用Stloc_3。
可以把这些指令用一个方法进行包装,源码如下
public static void StormLocal(ILGenerator ilGenerator, LocalBuilder localBuilder)
{
int localIndex = localBuilder.LocalIndex;
switch (localIndex)
{
case :
ilGenerator.Emit(OpCodes.Stloc_0);
return;
case :
ilGenerator.Emit(OpCodes.Stloc_1);
return;
case :
ilGenerator.Emit(OpCodes.Stloc_2);
return;
case :
ilGenerator.Emit(OpCodes.Stloc_3);
return;
}
if (localIndex > && localIndex <= )
{
ilGenerator.Emit(OpCodes.Stloc_S, localIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Stloc, localIndex);
return;
}
}
加载局部变量
把局部变量加载到运算栈上的指令是Ldloc、Ldloc_S、Ldloc_0、Ldloc_1、Ldloc_2、Ldloc_3。
Ldloc是通用指令;
当LocalBuilder的LocalIndex在0到255之间时,推荐用Ldloc_S;
当LocalBuilder的LocalIndex为0时,推荐用Ldloc_0;
当LocalBuilder的LocalIndex为1时,推荐用Ldloc_1;
当LocalBuilder的LocalIndex为2时,推荐用Ldloc_2;
当LocalBuilder的LocalIndex为3时,推荐用Ldloc_3。
可以把这些指令用一个方法进行包装,源码如下
public static void LoadLocal(ILGenerator ilGenerator,LocalBuilder localBuilder)
{
int localIndex = localBuilder.LocalIndex;
switch (localIndex)
{
case :
ilGenerator.Emit(OpCodes.Ldloc_0);
return;
case :
ilGenerator.Emit(OpCodes.Ldloc_1);
return;
case :
ilGenerator.Emit(OpCodes.Ldloc_2);
return;
case :
ilGenerator.Emit(OpCodes.Ldloc_3);
return;
}
if(localIndex> && localIndex<=)
{
ilGenerator.Emit(OpCodes.Ldloc_S, localIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Ldloc, localIndex);
return;
}
}
完整的程序如下
using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
class Demo04_Local
{
static string binaryName = "Demo04_Local.exe";
static string namespaceName = "LX1_ILDemo";
static string typeName = "EmitLocal"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder;
static MethodBuilder mainMethod;
static ILGenerator ilGenerator; static void Emit_ILCode()
{
MethodInfo writeIntLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
MethodInfo writeStringLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); /* string v1; */
LocalBuilder localBuilderv1 = ilGenerator.DeclareLocal(typeof(string));//声明一个string类型局部变量,第一次声明一个变量,所以它的LocalIndex是0 /* v1="hello"; */
ilGenerator.Emit(OpCodes.Ldstr,"hello");
ilGenerator.Emit(OpCodes. Stloc_0 );
/* Console.WriteLine(v1); */
ilGenerator.Emit(OpCodes.Ldloc_0);
ilGenerator.Emit(OpCodes.Call, writeStringLineMethod); /* v1="hello"; */
ilGenerator.Emit(OpCodes.Ldstr, "world");
StormLocal(ilGenerator, localBuilderv1);
/* Console.WriteLine(v1); */
LoadLocal(ilGenerator, localBuilderv1);
ilGenerator.Emit(OpCodes.Call, writeStringLineMethod); /* int v2; */
LocalBuilder localBuilderv2 = ilGenerator.DeclareLocal(typeof(int));//声明一个int类型局部变量,第二次声明一个变量,所以它的LocalIndex是1 /* v2=int.MaxValue; */
ilGenerator.Emit(OpCodes.Ldc_I4,int.MaxValue);
ilGenerator.Emit(OpCodes.Stloc_1);
/* Console.WriteLine(v2); */
ilGenerator.Emit(OpCodes.Ldloc_1);
ilGenerator.Emit(OpCodes.Call, writeIntLineMethod); /* v1=int.MinValue; */
ilGenerator.Emit(OpCodes.Ldc_I4, int.MinValue);
StormLocal(ilGenerator, localBuilderv2);
/* Console.WriteLine(v2); */
LoadLocal(ilGenerator, localBuilderv2);
ilGenerator.Emit(OpCodes.Call, writeIntLineMethod); } public static void LoadLocal(ILGenerator ilGenerator,LocalBuilder localBuilder)
{
int localIndex = localBuilder.LocalIndex;
switch (localIndex)
{
case :
ilGenerator.Emit(OpCodes.Ldloc_0);
return;
case :
ilGenerator.Emit(OpCodes.Ldloc_1);
return;
case :
ilGenerator.Emit(OpCodes.Ldloc_2);
return;
case :
ilGenerator.Emit(OpCodes.Ldloc_3);
return;
}
if(localIndex> && localIndex<=)
{
ilGenerator.Emit(OpCodes.Ldloc_S, localIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Ldloc, localIndex);
return;
}
} public static void StormLocal(ILGenerator ilGenerator, LocalBuilder localBuilder)
{
int localIndex = localBuilder.LocalIndex;
switch (localIndex)
{
case :
ilGenerator.Emit(OpCodes.Stloc_0);
return;
case :
ilGenerator.Emit(OpCodes.Stloc_1);
return;
case :
ilGenerator.Emit(OpCodes.Stloc_2);
return;
case :
ilGenerator.Emit(OpCodes.Stloc_3);
return;
}
if (localIndex > && localIndex <= )
{
ilGenerator.Emit(OpCodes.Stloc_S, localIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Stloc, localIndex);
return;
}
} public static void Generate()
{
InitAssembly(); /* 生成 public class LoadLFDSN */
typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public); /* 生成 public static void Main() */
GenerateMain(); Emit_ILCode(); EmitReadKey();
ilGenerator.Emit(OpCodes.Ret); /* 设置assembly入口方法 */
assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication); SaveAssembly();
Console.WriteLine("生成成功");
} 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实用指南-局部变量的声明、保存和加载的更多相关文章
- MSIL实用指南-生成索引器
MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...
- MSIL实用指南-Action的生成和调用
MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...
- TensorFlow模型保存和加载方法
TensorFlow模型保存和加载方法 模型保存 import tensorflow as tf w1 = tf.Variable(tf.constant(2.0, shape=[1]), name= ...
- 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别
[源码下载] 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) ...
- keras中的模型保存和加载
tensorflow中的模型常常是protobuf格式,这种格式既可以是二进制也可以是文本.keras模型保存和加载与tensorflow不同,keras中的模型保存和加载往往是保存成hdf5格式. ...
- 完美实现保存和加载easyui datagrid自定义调整列宽位置隐藏属性功能
需求&场景 例表查询是业务系统中使用最多也是最基础功能,但也是调整最平凡,不同的用户对数据的要求也不一样,所以在系统正式使用后,做为开发恨不得坐在业务边上,根据他们的要求进行调整,需要调整最多 ...
- 从头学pytorch(十二):模型保存和加载
模型读取和存储 总结下来,就是几个函数 torch.load()/torch.save() 通过python的pickle完成序列化与反序列化.完成内存<-->磁盘转换. Module.s ...
- 使用Pytorch在多GPU下保存和加载训练模型参数遇到的问题
最近使用Pytorch在学习一个深度学习项目,在模型保存和加载过程中遇到了问题,最终通过在网卡查找资料得已解决,故以此记之,以备忘却. 首先,是在使用多GPU进行模型训练的过程中,在保存模型参数时,应 ...
- MSIL实用指南-加载bool、sbyte、byte、char、short等值
这一篇讲解怎么加载bool值.sbyte值.byte值.char值.short值. 加载bool值在.NET程序实际运行中,是没有true和false值的,实际上是以1和0表示它们,加载它们的指令是L ...
随机推荐
- java复习笔记
本笔记(无异常处理与网络编程部分)整理自<java程序设计>-黄岚 王岩 王康平 编著 java数据 UI I/O java线程 数据库操作 Java数 ...
- dubbox系列【二】——dubbox admin环境搭建
1.环境 JDK7+ zookeeper 3.3.6 tomcat 7+ 2.搭建步骤 (1)安装zookeeper 单机模式:参考这里. 伪集群模式:参考这里. ①单机或伪集群模式均可. ②笔者使用 ...
- tcp/ip 卷一 读书笔记(2)物理层和链路层网络
物理层和链路层网络 术语 链路 是一对相邻结点间的物理线路,中间没有任何其他的交换结点. 数据链路 除了物理线路外,还必须有通信协议来控制这些数据的传输. 帧 数据链路层的协议数据单元(PDU) 串行 ...
- C语言视频简介
通过学习<C语言基础视频教程>,可以让你对C语言有一个基础的了解,并且会编写一些基础的程序,本次视频主要讲解的内容有: 1. 数字的进制转换 2. 变量.运算符和表达式 3. 流程控制语句 ...
- ios学习- 10大iOS开发者最喜爱的类库
该10大iOS开发者最喜爱的库由“iOS辅导团队”成员Marcelo Fabri组织投票选举而得,参与者包括开发者团队,iOS辅导团队以及行业嘉宾.每个团队都要根据以下规则选出五个最好的库: 1)不能 ...
- 【前端】Vue2全家桶案例《看漫画》之四、漫画页
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/vue_vux_app_4.html 项目github地址:https://github.com/shamoyuu/ ...
- 放大倍数超5万倍的Memcached DDoS反射攻击,怎么破?
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯游戏云 背景:Memcached攻击创造DDoS攻击流量纪录 近日,利用Memcached服务器实施反射DDoS攻击的事件呈大幅上 ...
- 关于SSDT
百度上比较好的解释是:SSDT的全称是System Services Descriptor Table,系统服务描述符表.这个表就是一个把ring3的Win32 API和ring0的内核API联系起来 ...
- 为Hi3531添加4串口支持
修改文件为 linux-3.0.y\arch\arm\mach-godnet\core.c linux-3.0.y\arch\arm\mach-godnet\include\mach\irqs.h 修 ...
- Android WebView编程的那些坑(一)
最大的坑是ROM不同,webkit不同,差异性很大.再加上google的坑,真是坑上加坑.比如js注入问题,比如client回调接口时序问题, 比如内存回收问题,etc 1.内存泄漏问题,尤其注意An ...