MSIL实用指南-加载和保存参数
本篇讲解怎么加载和保存参数,以及参数起始序号的确定。
参数的加载
加载参数的指令是Ldarg、Ldarg_S、Ldarg_0、Ldarg_1、Ldarg_2、Ldarg_3。
Ldarg_0是加载第0个参数,例子 ilGenerator.Emit(OpCodes.Ldarg_0);
Ldarg_1是加载第1个参数,例子 ilGenerator.Emit(OpCodes.Ldarg_1);
Ldarg_2是加载第2个参数,例子 ilGenerator.Emit(OpCodes.Ldarg_2);
Ldarg_3是加载第3个参数,例子 ilGenerator.Emit(OpCodes.Ldarg_3);
Ldarg_S是加载次序为0到255的参数,例子 ilGenerator.Emit(OpCodes.Ldarg_S,5);
Ldarg加载任意次序的参数,例子 ilGenerator.Emit(OpCodes.Ldarg,6)。
我们可以根据指令的说明实现一个方便调用的方法,源码如下
public static void LoadArg(ILGenerator ilGenerator, int argIndex)
{
switch (argIndex)
{
case :
ilGenerator.Emit(OpCodes.Ldarg_0);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_1);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_2);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_3);
return;
}
if (argIndex > && argIndex <= )
{
ilGenerator.Emit(OpCodes.Ldarg_S, argIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Ldarg, argIndex);
return;
}
}
参数的保存
保存参数的指令是Starg、Starg_S
Ldarg_S是保存次序为0到255的参数,例子 ilGenerator.Emit(OpCodes.Starg_S,1);
Starg加载任意次序的参数,例子 ilGenerator.Emit(OpCodes.Starg,6)。
我们可以根据指令的说明实现一个方便调用的方法,源码如下
public static void StormArg(ILGenerator ilGenerator, int argIndex)
{
if (argIndex > 0 && argIndex <= 255)
{
ilGenerator.Emit(OpCodes.Starg_S, argIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Starg, argIndex);
return;
}
}
参数起始序号的确定
参数的起始序号不一定从0开始,也可能从1开始,这是由方法是否是static决定的。
如果参数所在的方法是static修饰的,序号从0开始;
如果不是static修饰,则从0开始。
完整的一个例子如下
using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
class Demo08_Arg
{
static string binaryName = "Demo08_Arg.exe";
static string namespaceName = "LX1_ILDemo";
static string typeName = "ArgTest"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder;
static MethodBuilder mainMethod;
static MethodBuilder printStaticMethod;
static MethodBuilder printInstaceMethod;
static ConstructorBuilder constructorBuilder; static void Emit_PrintInstace()
{
printInstaceMethod = typeBuilder.DefineMethod("PrintInstanceArg", MethodAttributes.Public,
typeof(void), new Type[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(string) });
ILGenerator printILInstaceGenerator = printInstaceMethod.GetILGenerator();
ParameterBuilder ab1 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i1");
ParameterBuilder ab2 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i2");
ParameterBuilder ab3 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i3");
ParameterBuilder ab4 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i4");
ParameterBuilder ab5 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "s5"); MethodInfo writeIntLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
MethodInfo writeStringLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
LoadArg(printILInstaceGenerator,);
printILInstaceGenerator.Emit(OpCodes.Call, writeIntLineMethod);
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeIntLineMethod);
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeIntLineMethod);
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeIntLineMethod);
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeStringLineMethod);
printILInstaceGenerator.Emit(OpCodes.Ldstr, "world");
StormArg(printILInstaceGenerator, );
LoadArg(printILInstaceGenerator, );
printILInstaceGenerator.Emit(OpCodes.Call, writeStringLineMethod);
printILInstaceGenerator.Emit(OpCodes.Ret);
} public static void LoadArg(ILGenerator ilGenerator, int argIndex)
{
switch (argIndex)
{
case :
ilGenerator.Emit(OpCodes.Ldarg_0);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_1);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_2);
return;
case :
ilGenerator.Emit(OpCodes.Ldarg_3);
return;
}
if (argIndex > && argIndex <= )
{
ilGenerator.Emit(OpCodes.Ldarg_S, argIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Ldarg, argIndex);
return;
}
} public static void StormArg(ILGenerator ilGenerator, int argIndex)
{
if (argIndex > && argIndex <= )
{
ilGenerator.Emit(OpCodes.Starg_S, argIndex);
return;
}
else
{
ilGenerator.Emit(OpCodes.Starg, argIndex);
return;
}
} static void Emit_PrintStatic()
{
printStaticMethod = typeBuilder.DefineMethod("PrintStaticArg", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(string) });
ILGenerator printILGenerator = printStaticMethod.GetILGenerator();
ParameterBuilder ab1 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i1");
ParameterBuilder ab2 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i2");
ParameterBuilder ab3 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i3");
ParameterBuilder ab4 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "i4");
ParameterBuilder ab5 = printStaticMethod.DefineParameter(, ParameterAttributes.None, "s5"); MethodInfo writeIntLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
MethodInfo writeStringLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
printILGenerator.Emit(OpCodes.Ldarg_0);
printILGenerator.Emit(OpCodes.Call, writeIntLineMethod);
printILGenerator.Emit(OpCodes.Ldarg_1);
printILGenerator.Emit(OpCodes.Call, writeIntLineMethod);
printILGenerator.Emit(OpCodes.Ldarg_2);
printILGenerator.Emit(OpCodes.Call, writeIntLineMethod);
printILGenerator.Emit(OpCodes.Ldarg_3);
printILGenerator.Emit(OpCodes.Call, writeIntLineMethod);
printILGenerator.Emit(OpCodes.Ldarg_S,);
printILGenerator.Emit(OpCodes.Call, writeStringLineMethod);
printILGenerator.Emit(OpCodes.Ldstr, "world");
printILGenerator.Emit(OpCodes.Starg_S, );
printILGenerator.Emit(OpCodes.Ldarg_S, );
printILGenerator.Emit(OpCodes.Call, writeStringLineMethod);
printILGenerator.Emit(OpCodes.Ret);
} public static void Generate()
{
InitAssembly();
typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public);
constructorBuilder = typeBuilder.DefineDefaultConstructor( MethodAttributes.Public);
Emit_PrintStatic();
Emit_PrintInstace();
EmitMain(); /* 设置assembly入口方法 */
assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
SaveAssembly();
Console.WriteLine("生成成功");
} static void EmitMain()
{
mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { });
ILGenerator mainILGenerator = mainMethod.GetILGenerator(); mainILGenerator.Emit(OpCodes.Ldc_I4,(int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldstr,"hello static");
mainILGenerator.Emit(OpCodes.Call, printStaticMethod); LocalBuilder localBuilder = mainILGenerator.DeclareLocal(typeof(string));
mainILGenerator.Emit(OpCodes.Newobj, constructorBuilder);
mainILGenerator.Emit(OpCodes.Stloc_0);
mainILGenerator.Emit(OpCodes.Ldloc_0);
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldc_I4, (int));
mainILGenerator.Emit(OpCodes.Ldstr, "hello instance");
mainILGenerator.Emit(OpCodes.Call, printInstaceMethod); MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
mainILGenerator.Emit(OpCodes.Call, readKeyMethod);
mainILGenerator.Emit(OpCodes.Pop);
mainILGenerator.Emit(OpCodes.Ret); } 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实用指南-加载null、string、long、float、double等值
本篇讲述怎么加载null.string值.long值.float值.double值. 加载null不需要参数值,只要 Emit ldnull 其它几个命令要 Emit <指令> <值 ...
- MSIL实用指南-加载bool、sbyte、byte、char、short等值
这一篇讲解怎么加载bool值.sbyte值.byte值.char值.short值. 加载bool值在.NET程序实际运行中,是没有true和false值的,实际上是以1和0表示它们,加载它们的指令是L ...
- MSIL实用指南-加载int值
这一篇讲的是怎样加载整数值到运算栈上.这一类的指令都是以Ldc_I4开头. Ldc_I4类OpCodes的Ldc_I4字段的功能是把一个int值压入运算栈上.它的使用方法是ilGenerator.Em ...
- MSIL实用指南-创建方法和定义参数
本篇讲解实现创建方法.指定参数的名称.实现参数加out和ref修饰符.以及参数加默认值. 创建方法 创建方法用类TypeAttributes的 DefineMethod(string name, Me ...
- Knockout应用开发指南 第六章:加载或保存JSON数据
原文:Knockout应用开发指南 第六章:加载或保存JSON数据 加载或保存JSON数据 Knockout可以实现很复杂的客户端交互,但是几乎所有的web应用程序都要和服务器端交换数据(至少为了本地 ...
- MSIL实用指南-Action的生成和调用
MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...
- MSIL实用指南-生成索引器
MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...
- KnockoutJS 3.X API 第七章 其他技术(1) 加载和保存JSON数据
Knockout允许您实现复杂的客户端交互性,但几乎所有Web应用程序还需要与服务器交换数据,或至少将本地存储的数据序列化. 最方便的交换或存储数据的方式是JSON格式 - 大多数Ajax应用程序今天 ...
- Tensorflow模型加载与保存、Tensorboard简单使用
先上代码: from __future__ import absolute_import from __future__ import division from __future__ import ...
随机推荐
- Cobbler-自动化部署神器
Cobbler-自动化部署神器 前言: 网络安装服务器套件 Cobbler(补鞋匠)从前,我们一直在做装机民工这份很有前途的职业.自打若干年前 Red Hat 推出了 Kickstart,此后我们顿觉 ...
- spring-boot-plus后台快速开发脚手架之代码生成器使用
Generator 代码生成 _ _ _ _ (_) | | | | | | ___ _ __ _ __ _ _ __ __ _ ______| |__ ___ ___ | |_ ______ _ _ ...
- 黑羽压测 做 API接口功能测试
做功能测试 黑羽压测 是一款性能测试工具,但是我们也可以使用它,很方便的做 API接口功能测试 . 点击下方链接,观看 讲解视频 https://www.bilibili.com/video/av60 ...
- Waiting for 1 instance(s) to be deallocated
看是不是马虎,自己的xampp,也就是mysql有没有打开
- windows server 2008 R2中建立ftp站点
在windows server 2008 R2中建立ftp站点,要遵循以下步骤: (1) 开启IIS中的ftp服务: (2) 在IIS中建立ftp站点. 具体过程如下: (1) 开启IIS中的ftp服 ...
- Flink 从0到1学习—— 分享四本 Flink 国外的书和二十多篇 Paper 论文
前言 之前也分享了不少自己的文章,但是对于 Flink 来说,还是有不少新入门的朋友,这里给大家分享点 Flink 相关的资料(国外数据 pdf 和流处理相关的 Paper),期望可以帮你更好的理解 ...
- 按需制作最小的本地yum源
[需求背景] 有时候客户的环境里面只能离线安装文件,此时可以使用CentOS的ISO光盘作为本地源进行安装,或者是制作一个包含了YUM源服务的虚拟机. 无论上面的哪一种方式都不够轻量,我们自己的组件可 ...
- 如何阅读JDK源码
JDK源码阅读笔记: https://github.com/kangjianwei/LearningJDK 如何阅读源码,是每个程序员需要面临的一项挑战. 为什么需要阅读源码?从实用性的角度来看,主要 ...
- 使用富文本编辑器Kindeditor
今天在做需求的时候,遇到有一个字段,需要保存带有格式的内容,决定使用富文本框编辑器Kindeditor来实现,解决方法如下: 登录官网下载控件包: http://kindeditor.net/down ...
- java并发编程(二十)----(JUC集合)CopyOnWriteArrayList介绍
这一节开始我们正式来介绍JUC集合类.我们按照List.Set.Map.Queue的顺序来进行介绍.这一节我们来看一下CopyOnWriteArrayList. CopyOnWriteArrayLis ...