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 ...
随机推荐
- ch11 持有对象
Java集合的基本类型:List.Set.Queue.Map 使用容器时若未指定泛型参数ArrayList apples=new ArrayList();,则容器中所有元素都为Object类型,使用时 ...
- js获取某个日期所在周周一的日期
第一次写,做个小笔记. 第一步:获取该日期的星期数: 第二步:在该日期上减去他的星期数再减1,(注:星期日获取到的星期数是0): 下面是具体代码: function GetMonday(dd) { v ...
- ansible基本使用教程
转载请注明出处http://www.cnblogs.com/chenxianpao/p/7360349.html 一. 介绍 1. 简介 ansible是新出现的自动化运维工具,基于Pytho ...
- UVA-11882 bfs + dfs + 剪枝
假设当前已经到达(x,y),用bfs判断一下还可以到达的点有maxd个,如果maxd加上当前已经经过的长度小于当前答案的长度就退出,如果相同,就将bfs搜索到的点从大到小排序,如果连最大序列都无法大于 ...
- chrome使用Timeline做性能分析
使用Timeline做性能分析 Timeline面板记录和分析了web应用运行时的所有活动情况,这是研究和查找性能问题的最佳途径.###Timeline面板概览 Timeline面板主要有三个部分构成 ...
- hive:条件判断函数
参考hive常用运算. •If函数: if •非空查找函数: COALESCE •条件判断函数:CASE • If 函数 : if 语法: if(boolean testCondition, T va ...
- Web渗透测试(sql注入 access,mssql,mysql,oracle,)
Access数据库注入: access数据库由微软发布的关系型数据库(小型的),安全性差. access数据库后缀名位*.mdb, asp中连接字符串应用-- "Driver={micros ...
- R+OCR︱借助tesseract包实现图片文本提取功能
2016年11月,Jeroen Ooms在CRAN发布了tesseract包,实现了R语言对简单图片的文本提取.分析功能. 利用开源OCR引擎进行图片处理,目前可以识别超过100种语言,R语言可以借助 ...
- VxWorks 任务
任务:在执行时每个程序都被称之为任务.VxWorks操作系统中,任务可以直接地或者以共享方式访问大多数系统资源,为了维护各自的线程,每个任务必须保持有足够的上下文环境.(1) 任务状态:就绪(R ...
- TI Davinci DM6446开发攻略——根文件系统的裁剪和移植
一.补充文件系统知识 Linux根文件系统是存放tool软件.lib文件.script(脚本).配置文件.其他特殊文件.自己开发的应用程序的地方.嵌入式linux的根文件系统rootfs就像windo ...