MSIL实用指南-加载nullstringlongfloatdouble等值

Posted TKT2016

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MSIL实用指南-加载nullstringlongfloatdouble等值相关的知识,希望对你有一定的参考价值。

本篇讲述怎么加载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)120);//数值前面的强制转换‘(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);
        }
    }
}
View Code

 

以上是关于MSIL实用指南-加载nullstringlongfloatdouble等值的主要内容,如果未能解决你的问题,请参考以下文章

MSIL实用指南-局部变量的声明保存和加载

MSIL实用指南-比较运算

MSIL实用指南-生成属性

MSIL实用指南-类相关生成

MSIL实用指南-方法的调用

MSIL实用指南-数据类型转换