我们学习编程开始时,一般用输出"hello world"的一段程序。

C#版的"hello world"是

using System;

namespace L01_HelloDemo
{
class HelloWorld
{
class Hello
{
public static void Main2()
{
Console.WriteLine("Hello World!");
Console.ReadKey();
}
}
}
}

用生成IL方式也可以输出"hello world",它的实现源码是

using System;
using System.Reflection;
using System.Reflection.Emit; namespace L01_HelloDemo
{
class HelloWorldILGenerator
{
static string binaryName = "ILHelloWorldDemo.exe";
static string namespaceName = "ILHelloWorldDemo";
static string typeName = "HelloWorld"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder; public static void Generate()
{
InitAssembly(); /* 生成 public class HelloWorld */
typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public); /* 生成 public static void Main() */
MethodBuilder mainMethod = typeBuilder.DefineMethod("Main",MethodAttributes.Public | MethodAttributes.Static, typeof(void), new Type[] { });
ILGenerator methIL = mainMethod.GetILGenerator(); /* 生成 Console.WriteLine("Hello World!"); */
MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine",new Type[]{ typeof(string) });
methIL.Emit(OpCodes.Ldstr, "Hello World!");
methIL.Emit(OpCodes.Call, writeLineMethod); /* 生成 Console.ReadKey(); */
MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
methIL.Emit(OpCodes.Call, readKeyMethod);
methIL.Emit(OpCodes.Pop); methIL.Emit(OpCodes.Ret); /* 设置assembly入口方法 */
assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication); SaveAssembly();
Console.WriteLine("生成成功");
Console.ReadKey();
} 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);
}
}
}

调用 HelloWorldILGenerator.Generate()后生成ILHelloWorldDemo.exe文件,打开它运行的效果和C#版的"hello world"的是一样的,

用ILSpy对ILHelloWorldDemo.exe进行反编译,反编译的源码也和和C#版的"hello world"的是一样的。

MSIL实用指南-IL版hello world的更多相关文章

  1. MSIL实用指南-生成索引器

    MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...

  2. MSIL实用指南-Action的生成和调用

    MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...

  3. MSIL实用指南-加载bool、sbyte、byte、char、short等值

    这一篇讲解怎么加载bool值.sbyte值.byte值.char值.short值. 加载bool值在.NET程序实际运行中,是没有true和false值的,实际上是以1和0表示它们,加载它们的指令是L ...

  4. MSIL实用指南-闭包的生成和调用

    闭包(Closure)是词法闭包(Lexical Closure)的简称.对闭包的具体定义有很多种说法,这些说法大体可以分为两类: 一种说法认为闭包是符合一定条件的函数,比如参考资源中这样定义闭包:闭 ...

  5. MSIL实用指南-给字段、属性、方法、类、程序集加Attribute

    C#编程中可以给字段.方法.类以及程序集加特性即继承于Attribute的类.这里讲解怎么在IL中给它们加上特性. 生成字段的对应的类是FieldBuilder,生成属性的对应的类是PropertyB ...

  6. MSIL实用指南-比较运算

    数值的比较就是大于.小于.等于.大于等于.小于等于.不等于,它们的运算结果都是布尔值.大于.小于.等于有直接对应的指令,分别是Cgt.Clt.Ceq.大于等于.小于等于.不等于没有直接对应的指令,它的 ...

  7. MSIL实用指南-加载int值

    这一篇讲的是怎样加载整数值到运算栈上.这一类的指令都是以Ldc_I4开头. Ldc_I4类OpCodes的Ldc_I4字段的功能是把一个int值压入运算栈上.它的使用方法是ilGenerator.Em ...

  8. MSIL实用指南-加载null、string、long、float、double等值

    本篇讲述怎么加载null.string值.long值.float值.double值. 加载null不需要参数值,只要 Emit ldnull 其它几个命令要 Emit <指令> <值 ...

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

    这一篇讲解方法内的局部变量是怎么声明.怎样保存.怎样加载的. 声明局部变量声明用ILGenerator的DeclareLocal方法,参数是局部变量的数据类型,得到一个局部变量对应的创建类LocalB ...

随机推荐

  1. CentOS时间的查看与修改

    [http://www.centoscn.com/CentOS/help/2014/0805/3430.html] 1.查看.修改Linux时区与时间 一.linux时区的查看与修改 1,查看当前时区 ...

  2. Java基础系列--static关键字

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/8477914.html 一.概述 static关键字是Java诸多关键字中较常使用的一个,从 ...

  3. IE8兼容问题总结---trim()方法

    1.IE8不支持,jquery的trim()去空格的方法 错误表现 : 会报错,对象不支持此属性或方法; 解决办法 : 使用正则匹配空格 例如 : /^\s+|\s+$/greplace(/^\s+| ...

  4. C/C++语言简介之运算符

    比较特别的是,比特右移(>>)运算符可以是算术(左端补最高有效位)或是逻辑(左端补 0)位移.例如,将 11100011 右移 3 比特,算术右移后成为 11111100,逻辑右移则为 0 ...

  5. MySQL Server 5.0安装教程

    相信很多朋友刚开始接触mysql数据库服务器,下面是mysql的安装教程,步骤明细也有详细的说明. 工具/原料   mysql MySQL安装的图解   1 打开下载的mysql安装文件mysql-5 ...

  6. hibhibernate中hql中的语句where语句查询List出现空

    1.java.sql.Date 与 java.util.Date java.sql.Date是从java.util.Date中继承而来 假设 dates1(java.sql.Date)要赋值给date ...

  7. java4 - 函数(方法)

    一.学习大纲: 1. 定义函数可以将功能封装 2. 函数的级别都是同级别的,不能进行函数套用 3. 便于对该功能进行复用 4. 函数只有被调用才能被执行 5. 函数的出现提高了代码的复用性 6. 函数 ...

  8. mysql主键,外键,索引

    主键 唯一而非空,只能有一个 作用: 1.唯一的标识一行  2.作为一个可以被外键有效引用的对象  3.保证数据完整性 设计原则: 1. 主键应当是对用户没有意义的.如果用户看到了一个表示多对多关系的 ...

  9. linux iptables配置

    防火墙硬件防火墙软件防火墙: 应用层防火墙 网络层防火墙:linux包过滤防火墙linux包过滤防火墙netfilter:位于linux内核中的包过滤功能体系,称为linux防火墙的"内核态 ...

  10. Linux基础一

    基本命令 useradd xxx 创建一个用户 uname     查看系统架构信息 uname -a  显示详细信息 uname -r  显示内核信息 date      显示当前网络时间 cat ...