前言

一般的只有最终的汇编代码才有机器码表示,然一个偶然的机会发现,MSIL(Microsoft intermediate language)作为一个中间语言表示,居然也有机器码,其实这也难怪,计算机里面万物都是二进制,本篇来看下。原文:在此处

概括

1.C# And IL

先上C#代码:

static void Main()
{
Program pm=new Program();
GC.Collect();
Console.WriteLine("CeShi JITDUMP");
Console.ReadLine();
}

非常简单的一段代码,把这段代码编译后的DLL导入到微软官方的ILDASM工具里面去,可以看到如下代码:

.method private hidebysig static void  Main() cil managed
{
.entrypoint
// 代码大小 28 (0x1c)
.maxstack 8
IL_0000: newobj instance void Program::.ctor()
IL_0005: pop
IL_0006: call void [System.Runtime]System.GC::Collect()
IL_000b: ldstr "CeShi JITDUMP"
IL_0010: call void [System.Console]System.Console::WriteLine(string)
IL_0015: call string [System.Console]System.Console::ReadLine()
IL_001a: pop
IL_001b: ret
} // end of method Program::Main

这里注意下标号IL_0000的那段代码:

IL_0000:  newobj     instance void Program::.ctor()

以此为例子作为观察。

2.JIT Import IL

来看下JIT把这段IL代码导入后的一个情况

IL to import:
IL_0000 73 04 00 00 06 newobj 0x6000004
IL_0005 26 pop
IL_0006 28 0e 00 00 0a call 0xA00000E
IL_000b 72 01 00 00 70 ldstr 0x70000001
IL_0010 28 0f 00 00 0a call 0xA00000F
IL_0015 28 10 00 00 0a call 0xA000010
IL_001a 26 pop
IL_001b 2a ret

注意到JIT导入这段IL代码之后,多了机器码,多了十六进制的表示。以IL_0000段代码为例

导入之前:

 IL_0000:  newobj     instance void Program::.ctor()

这里newobj之前没有机器码,newobj之后是调用了函数instance void Program::.ctor()。

导入之后:

IL_0000  73 04 00 00 06    newobj       0x6000004

这里很明显看到变化,newobj之前有一连串的机器码:73 04 00 00 06。newobj之后,则有十六进制0x6000004取代了上面的函数调用:instance void Program::.ctor()。

3.分析

那么IL里面的这些机器码和十六进制数值是干什么用的呢?

首先看下机器码:73 04 00 00 06。一个个的看。

首先的0x73,它表示的是:newobj的机器码。它的原型是:

OPDEF(CEE_NEWOBJ, "newobj",VarPop,PushRef,InlineMethod,   IObjModel, 1,0xFF,0x73,CALL)

后面的04 00 00 06这四个字节的机器码可以看做一个整体,小端取值那么它的值是:6000004。

那么这个6000004到底表示什么东西呢?通过ILDASM的快捷键Ctrl+M打开元数据信息,里面可以看到6000004表示的就是.ctor函数的元数据描述,它的原型如下:

Method #2 (06000004)
-------------------------------------------------------
MethodName: .ctor (06000004)
Flags : [Public] [HideBySig] [ReuseSlot] [SpecialName] [RTSpecialName] [.ctor] (00001886)
RVA : 0x00002084
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.

那么这段代码

IL_0000  73 04 00 00 06    newobj       0x6000004

的整体意思就很清楚了,73 04 00 00 06里面的73是表示newobj,后面的04 00 00 06表示调用.ctor非静态构造函数。它实际上跟ILDASM里面显示的是同一个意思,但是因为在内存里面操作,所以它只能是十六进制或者二进制,JIT导入的时候只不过把字母的含义替换成了具体数字的含义。

结尾

作者:江湖评谈

欢迎关注我的公众号,顶级文章的首发地。

罕见的技术:MSIL的机器码简析的更多相关文章

  1. [转帖]简析数据中心三大Overlay技术

    简析数据中心三大Overlay技术 http://www.jifang360.com/news/20161010/n225987768.html 搭建大规模的云计算环境需要数据中心突破多种技术难题,其 ...

  2. 简析 .NET Core 构成体系

    简析 .NET Core 构成体系 Roslyn 编译器 RyuJIT 编译器 CoreCLR & CoreRT CoreFX(.NET Core Libraries) .NET Core 代 ...

  3. DiskGenius注册算法简析

    初次接触DiskGenius已经成为遥远的记忆,那个时候还只有DOS版本.后来到Windows版,用它来处理过几个找回丢失分区的案例,方便实用.到现在它的功能越来越强大,成为喜好启动技术和桌面支持人员 ...

  4. 简析.NET Core 以及与 .NET Framework的关系

    简析.NET Core 以及与 .NET Framework的关系 一 .NET 的 Framework 们 二 .NET Core的到来 1. Runtime 2. Unified BCL 3. W ...

  5. Linux 目录结构学习与简析 Part2

    linux目录结构学习与简析 by:授客 QQ:1033553122 ---------------接Part 1-------------- #1.查看CPU信息 #cat /proc/cpuinf ...

  6. XMR恶意挖矿案例简析

    前言 数字货币因其技术去中性化和经济价值等属性,逐渐成为大众关注的焦点,同时通过恶意挖矿获取数字货币是黑灰色产业获取收益的重要途径.本文简析通过蜜罐获取的XMR恶意挖矿事件:攻击者通过爆破SSH获取系 ...

  7. 简析 Tomcat 、Nginx 与 Apache 的区别

    简析 Tomcat .Nginx 与 Apache 的区别 本文讲的是简析 Tomcat .Nginx 与Apache的区别, 经常在用 apache 和 tomcat 等这些服务器,可是总感觉还是不 ...

  8. JDK框架简析--java.lang包中的基础类库、基础数据类型

    题记 JDK.Java Development Kit. 我们必须先认识到,JDK不过,不过一套Java基础类库而已,是Sun公司开发的基础类库,仅此而已,JDK本身和我们自行书写总结的类库,从技术含 ...

  9. Linux网络性能优化方法简析

    Linux网络性能优化方法简析 2010-12-20 10:56 赵军 IBMDW 字号:T | T 性能问题永远是永恒的主题之一,而Linux在网络性能方面的优势则显而易见,这篇文章是对于Linux ...

  10. 痞子衡嵌入式:简析i.MXRT1170 Cortex-M4 L-MEM ECC功能特点、开启步骤、性能影响

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M4内核的L-MEM ECC功能. 本篇是 <简析i.MXRT1170 Cortex-M ...

随机推荐

  1. python3常用模块和方法

    1.使用索引反转字符串 str="hello" print(str[::-1]) 2.zip函数获取可迭代对象,将它们聚合到一个元组中,然后返回结果.语法是zip(*iterabl ...

  2. 设计模式(三十)----综合应用-自定义Spring框架-自定义Spring IOC-定义bean、注册表相关类

    现要对下面的配置文件进行解析,并自定义Spring框架的IOC对涉及到的对象进行管理. <?xml version="1.0" encoding="UTF-8&qu ...

  3. ACM-NEFU15届校赛-大一组

    A. 三角形面积 #include <bits/stdc++.h> using namespace std; int main() { double a,b,c; double ans,p ...

  4. Kubernetes 部署 MySQL 高可用读写分离

    Kubernetes 部署 MySQL 高可用读写分离 简介: 在有状态应用中,MySQL是我们最常见也是最常用的.本文我们将实战部署一个一组多从的MySQL集群. 一.配置准备 configMap ...

  5. Ubuntu 通过 Netplan 配置网络教程

    Ubuntu 通过 Netplan 配置网络教程 Ubuntu through Netplan configuration network tutorial 一.Netplan 配置流程 1. Net ...

  6. python 启动外部程序四种方法

    在Python中,可以方便地使用os模块来运行其他脚本或者程序,这样就可以在脚本中直接使用其他脚本或程序提供的功能,而不必再次编写实现该功能的代码.为了更好地控制运行的进程,可以使用win32proc ...

  7. Jmix 如何将外部数据直接显示在界面?

    企业级应用中,通常一个业务系统并不是孤立存在的,而是需要与企业.部门或者是外部的已有系统进行集成.一般而言,系统集成的数据和接口交互方式通常有以下几种: 文件传输:通过文件传输的方式将数据传递给其他系 ...

  8. 【Note】倍增

    真的不会.QAQ 目录 简介 大家都见过的应用:倍增求 \(\text{LCA}\) 倍增求 \(\text{LCA}\) ,但是动态加点,但是不会 \(lct\) 例题:[ZJOI2012]灾难(D ...

  9. Golang一日一库之 日志库 zap

    简介 在开发过程中 会使用到日志库去记录错误的日志,尤其是golang中 有无穷无尽的error 如果不记录,当你的代码出错,就无从排错了. zap 是开源的 Go 高性能日志库 主要有以下特点: 支 ...

  10. Vue修改单页面背景颜色