MSIL实用指南-IL版hello world
我们学习编程开始时,一般用输出"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的更多相关文章
- MSIL实用指南-生成索引器
MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...
- MSIL实用指南-Action的生成和调用
MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...
- MSIL实用指南-加载bool、sbyte、byte、char、short等值
这一篇讲解怎么加载bool值.sbyte值.byte值.char值.short值. 加载bool值在.NET程序实际运行中,是没有true和false值的,实际上是以1和0表示它们,加载它们的指令是L ...
- MSIL实用指南-闭包的生成和调用
闭包(Closure)是词法闭包(Lexical Closure)的简称.对闭包的具体定义有很多种说法,这些说法大体可以分为两类: 一种说法认为闭包是符合一定条件的函数,比如参考资源中这样定义闭包:闭 ...
- MSIL实用指南-给字段、属性、方法、类、程序集加Attribute
C#编程中可以给字段.方法.类以及程序集加特性即继承于Attribute的类.这里讲解怎么在IL中给它们加上特性. 生成字段的对应的类是FieldBuilder,生成属性的对应的类是PropertyB ...
- MSIL实用指南-比较运算
数值的比较就是大于.小于.等于.大于等于.小于等于.不等于,它们的运算结果都是布尔值.大于.小于.等于有直接对应的指令,分别是Cgt.Clt.Ceq.大于等于.小于等于.不等于没有直接对应的指令,它的 ...
- MSIL实用指南-加载int值
这一篇讲的是怎样加载整数值到运算栈上.这一类的指令都是以Ldc_I4开头. Ldc_I4类OpCodes的Ldc_I4字段的功能是把一个int值压入运算栈上.它的使用方法是ilGenerator.Em ...
- MSIL实用指南-加载null、string、long、float、double等值
本篇讲述怎么加载null.string值.long值.float值.double值. 加载null不需要参数值,只要 Emit ldnull 其它几个命令要 Emit <指令> <值 ...
- MSIL实用指南-局部变量的声明、保存和加载
这一篇讲解方法内的局部变量是怎么声明.怎样保存.怎样加载的. 声明局部变量声明用ILGenerator的DeclareLocal方法,参数是局部变量的数据类型,得到一个局部变量对应的创建类LocalB ...
随机推荐
- Docker Centos7 下建立 Docker 桥接网络
为什么要让docker桥接物理网络? docker默认提供了一个隔离的内网环境,启动时会建立一个docker0的虚拟网卡,每个容器都是连接到docker0网卡上的.而docker0的ip段为172.1 ...
- 织梦默认编辑器 按下回车生成br标签改为生成p标签
找到文件 \include\ckeditor\config.js 把 config.enterMode = CKEDITOR.ENTER_BR; config.shiftEnterMode = CKE ...
- 试着把.net的GC讲清楚(2)
试着把.net的GC讲清楚(1) 上篇文章说了一些基本概念的东西,然后还有很多东西概念没有头绪,这篇文章我试着解释 GC的回收算法详细步骤? 上篇]文章讲了.net GC的算法是Mark and Co ...
- 通过实例介绍持续集成的应用--基于Jenkins
1.测试工程师为什么要掌握持续集成 一个程序员如果想发布一个产品,他需要编码.编译.测试,发布的过程.对于一个企业来说,如果也想发布一个产品的话,同样的也是需要上述的过程,区别在于企业要发布的产品的需 ...
- 获取目录-Winform
// 获取程序的基目录. System.AppDomain.CurrentDomain.BaseDirectory // 获取模块的完整路径. System.Diagnostics.Process.G ...
- XP环境下的网络证书问题
项目过程中,由于是收银系统需要从服务器获取支付二维码,会产生SSL连接的问题,在win7.win10上都没有问题,放到WIN XP上出现了The underlying connection was c ...
- 【剑指offer】04替换空格,C++实现
0.前言 # 替换空格为字符串部分的题目,剑指offer中字符串系列的文章地址,剑指offer全系列文章地址 1.题目 # 请实现一个函数,将一个字符串中的空格替换成"%20".例 ...
- 使用CrashHandler来获取应用的crash信息
源码地址https://github.com/king1039/android-art-res/tree/master/Chapter_13/CrashTest/src/com/ryg/crashte ...
- HDU - 1067 Gap (bfs + hash) [kuangbin带你飞]专题二
题意: 起初定28张卡牌的排列,把其中11, 21, 31, 41移动到第一列,然后就出现四个空白,每个空白可以用它的前面一个数的下一个数填充,例如43后面的空格可以用44填充,但是47后面即 ...
- Web开发框架推导
本文欲回答这样一个问题:在 「特定环境 」下,如何规划Web开发框架,使其能满足 「期望 」? 假设我们的「特定环境 」如下: 技术层面 使用Java语言进行开发 通过Maven构建 基于Spring ...