《你必须知道的.NET》读书笔记:从Hello World认识IL

通用的语言基础是.NET运行的基础,当我们对程序运行的结果有异议的时候,如何透过本质看表面,需要我们从底层来入手探索,这时候,IL便是我们必须知道的基础。

一、IL基础概念

1.1 什么是IL?

  IL是.NET框架中间语言(Intermediate Language)的缩写。使用.NET框架提供的编译器可以直接将源程序编译为.exe或.dll文件,但此时编译出来的程序代码并不是CPU能直接执行的机器代码,而是一种中间语言IL(Intermediate Language)的代码。

1.2 为何要了解IL?

  元数据和IL是CLR的基础,了解必要的IL是深入认识CLR的捷径,我们没有理由放弃一条可以直接通达大门的便捷之路而盲目地以其他的方式追求深入。同时,大量的事例分析都是以IL来揭秘的,因此了解IL是读懂他人代码的必备基础,可以给自己更多的收获。

二、IL分析工具

2.1 ILASM.exe和ILDASM.exe

  .NET Framework中自带了一套成熟的编译于反编译利器:ILASM.exe和ILDASM.exe,其中ILASM.exe工具用来执行IL代码并生成可执行程序,而ILDASM.exe则用来反编译可执行程序(反编译为IL代码进行查看)。

2.2 Reflector.exe

  Reflector是由微软员工Lutz Roeder编写的免费程序。Reflector的出现使·NET程序员眼前豁然开朗,因为这个免费工具可以将·NET程序集中的IL反编译成C#或者Visual Basic代码。除了能将IL转换为C#或Visual Basic以外,Reflector还能够提供程序集中类及其成员的概要信息、提供查看程序集中IL的能力以及提供对第三方插件的支持。

三、一个Hello World的IL之旅

3.1 准备一个Hello World程序

using System;
using System.Data;

namespace HelloIL
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

3.2 利用ILDASM体验IL

(1)对编译后的可执行文件HelloIL.exe,使用ILDasm.exe进行反编译,将会还原HelloIL为IL编码,结构如下:

  分为两个部分:MANIFEST和HelloIL程序集。

(2)其中,MANIFEST是附加信息列表,主要包含了程序集的一些属性:程序集名称、版本号、哈希算法、程序集模块等,以及对外部引用程序集的引用项:

// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly HelloIL
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
.module HelloIL.exe
// MVID: {C176F7F5-9415-4616-A709-E08967A0C6A0}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x00000000003C0000

  ① .assembly指令用于定义编译目标或者加载外部库:这里只加载了mscorlib核心库,而System.Data被忽略,有效避免了过度加载引起的代码膨胀;

  ② .ctor指令表示构造函数,代码里没有任何显示构造函数,因此这里调用基类System.Object的构造函数(System.Object位于mscorlib程序集中);

  (3)其次,HelloIL程序集是我们要分析的重点:

  ① 首先是Program类

  ② 然后是ctor方法(构造方法)

  ③ 最后是Main方法

  (4)化繁为简,一览天下

  这里将上面的IL代码简化一下,去粗取精来展现一下上面示例的IL代码,详细的分析以注释方式描述:

    // 加载外部程序集
    .assembly extern mscorlib
    // 指定编译目标程序集
    .assembly HelloIL

    .class Program extends [mscorlib]System.Object
    {
        .method public instanct void .ctor() cil managed
        {
            .maxstack 8
            // 调用基类构造函数
            ldarg.0
            call instance void [mscorlib]System.Object::.ctor()
            // 执行完毕,返回
            ret
        }

        .method static void Main() cil managed
        {
            // 表明程序入口点
            .entrypoint
            .maxstack 8
            // 装载string对象
            ldstr "Hello World!"
            // 调用静态方法WriteLine
            call void [mscorlib]System.Console::WriteLine(string)
            // 执行完毕,返回
            ret
        }
    }

3.3 IL体验小结

通过一个Hello World示例,我们和IL进行了第一次的亲密接触。认识IL,是个循序渐进的过程,有了本次的小示例作为铺垫,我们可以轻松地认识简单的IL代码了。

参考资料

(1)本文源自王涛(anytao)的《你必须知道的.NET(第二版)》,感谢金馆长熊猫表情。

(2)Zery,《读懂IL就这么简单(一)

作者:周旭龙

出处:http://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

【翻译】为什么 goroutine 的栈内存无穷大?

一些 Go 语言的新学习者总是会对 goroutine 栈内存占用大小感到非常好奇。这一般是由于程序员进行无限的函数循环调用导致的。为了说明这个问题,请思考以下...

3626
来自专栏葡萄城控件技术团队

C# 8.0的三个值得关注的新特性

1353
来自专栏Urahara Blog

Using get_defined_functions To Hidden A PHP Backdoor

1792
来自专栏安恒网络空间安全讲武堂

赛前福利②最新2018HITB国际赛writeup

FIRST 距离“西湖论剑杯”全国大学生网络空间安全技能大赛只有9天啦! 要拿大奖、赢offer,那必须得来点赛前练习定定心啊~这不,讲武堂就拿到了2018HI...

3404
来自专栏Java架构

2018年Java程序员最新BAT面试题

3756
来自专栏灯塔大数据

技术 | Python从零开始系列连载(十五)

在Python中使用try...except 结构创建 ' 隔离区 ',也就是进行异常处理

951
来自专栏Golang语言社区

无辜的goroutine

简介: 本文主要是针对一些对于goroutine的“指控”提出我自己的看法,特别是轩脉刃的一篇博客文章《论go语言中goroutine的使用》提出了gorout...

36811
来自专栏Pythonista

Python之路,Day1 - Python基础1

python的创始人为吉多·范罗苏姆(Guido van Rossum)。1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解...

1995
来自专栏玄魂工作室

Hacker基础之Python篇:一、环境安装和基础知识

0x01. 前言 emmmmmmm...你只需知道这是一门用途很广的语言,上到大数据AI,下到Linux运维,都可以使用Python,当然,黑客也用Pyth...

3026
来自专栏狮乐园

简单探索 js 中 something >> 0 的原理

关于这个问题是今天改公司项目小程序的一个bug时看到的,修复这个bug的解决方法是需要引入 String.prototype.padStart 的 polyfi...

1183

扫码关注云+社区

领取腾讯云代金券