详解.NET IL代码

news2024/11/17 12:47:48

IL是什么?

 Intermediate Language (IL)微软中间语言

C#代码编译过程?

C#源代码通过LC转为IL代码,IL主要包含一些元数据和中间语言指令;

JIT编译器把IL代码转为机器识别的机器代码。如下图

语言编译器:无论是VB code还是C# code都会被Language Compiler转换为MSIL

MSIL的作用:MSIL包含一些元数据和中间语言指令

JIT编译器的作用:根据系统环境将MSIL中间语言指令转换为机器码

为什么ASP.NET网站第一次运行时会较慢,而后面的执行速度则会相对快很多?

当你第一次运行.NET开发的站点时,CLR会将MSIL通过JIT进行编译,最终转换为执行速度非常快的Native Code。这可以解释。

为什么要了解IL代码?

如果想学好.NET,IL是必须的基础,IL代码是.NET运行的基础,当我们对运行结果有异议的时候,可以通过IL代码透过表面看本质;

IL也是更好理解、认识CLR的基础;

大量的实例分析是以IL为基础的,所以了解IL,是读懂他人代码的必备基础,同时自己也可以获得潜移默化的提高;

二、如何把ILDasm导入到VS中

想要看IL代码需要使用ILDasm工具,工具一般在电脑的

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\ildasm.exe

也可以下载ILSpy:http://ilspy.net/

把ILDasm导入到VS工具中,使用方便,具体如下:工具 - > 外部工具 

  

导入之后,vs工具里面就有ILDasm工具了。以后想看IL代码方便多了。

IL代码通过ILDasm反编译后(左图),ILDasm图标意义(右图)

  

三、分析IL代码

在分析IL代码之前,要先理解几个概念:

图片来源:.NET中間語言(IL) | Microsoft Learn

Managed Heap(托管堆):这就是NET中的托管堆,用来存放引用类型,它是由GC(垃圾回收器自动进行回收)管理;

Call Stack(调用堆栈):调用堆栈:调用堆栈是一个方法列表,按调用顺序保存所有在运行期被调用的方法。

Evaluation Stack(计算堆栈):每个线程都有自己的线程栈,IL 里面的任何计算,都发生在 Evaluation Stack 上,其实就是一个 Stack 结构。可以 Push,也可以 Pop。

可以对照IL指令:指令列表,一步一步来分析IL代码

1、用C#写一个简单控制台应用程序

using System;

namespace ILDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 1;
            int j = 2;
            int k = 3;
            int answer = i + j + k;
            Console.WriteLine("i+j+k=" + answer);
            Console.ReadKey();
        }
    }
}

2、 用ILDasm打开bin下的.exe文件查看代码,具体IL代码如下:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint 
  // 代码大小       42 (0x2a)
  .maxstack  2
  .locals init ([0] int32 i,
           [1] int32 j,
           [2] int32 k,
           [3] int32 answer)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  stloc.0
  IL_0003:  ldc.i4.2
  IL_0004:  stloc.1
  IL_0005:  ldc.i4.3
  IL_0006:  stloc.2
  IL_0007:  ldloc.0
  IL_0008:  ldloc.1
  IL_0009:  add
  IL_000a:  ldloc.2
  IL_000b:  add
  IL_000c:  stloc.3
  IL_000d:  ldstr      "i+j+k="
  IL_0012:  ldloc.3
  IL_0013:  box        [mscorlib]System.Int32
  IL_0018:  call       string [mscorlib]System.String::Concat(object,
                                                              object)
  IL_001d:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0022:  nop
  IL_0023:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_0028:  pop
  IL_0029:  ret
} // end of method Program::Main

3、会用到的IL指令:

nop:无操作

ret:从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。

call:调用由传递的方法说明符指示的方法。

box:将值类转换为对象引用,就是装箱,同理可以知道拆箱unbox

ldc.i4.X:把int32的值推送到计算堆栈

stloc.X:把计算堆栈顶部的值放到调用堆栈索引为X处

ldloc.X:把调用堆栈X处的值复制到计算堆栈

4、理解注释后的代码

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint  //程序入口
  // 代码大小       42 (0x2a)
  .maxstack  2    // 计算出计算堆栈的能存几个值

  .locals init ([0] int32 i,
           [1] int32 j,
           [2] int32 k,
           [3] int32 answer) //定义int32类型的i,j,k,answer

  IL_0000:  nop   //无操作

  IL_0001:  ldc.i4.1  //把i的值放到计算堆栈上
  IL_0002:  stloc.0   //把计算堆栈顶部的值(i的值)放到调用堆栈索引0处
  IL_0003:  ldc.i4.2  //把j的值放到计算堆栈上
  IL_0004:  stloc.1   //把计算堆栈顶部的值(j的值)放到调用堆栈索引1处
  IL_0005:  ldc.i4.3  //把k的值放到计算堆栈上
  IL_0006:  stloc.2   //把计算堆栈顶部的值(k的值)放到调用堆栈索引2处

  IL_0007:  ldloc.0   //把调用堆栈索引为0处的值复制到计算堆栈 
  IL_0008:  ldloc.1   //把调用堆栈索引为1处的值复制到计算堆栈
  IL_0009:  add       //相加
  IL_000a:  ldloc.2   //把调用堆栈索引为2处的值复制到计算堆栈
  IL_000b:  add       //相加
  IL_000c:  stloc.3   //把计算堆栈顶部的值(add的值)放到调用堆栈索引3处
  IL_000d:  ldstr      "i+j+k="  //推送对元数据中存储的字符串的新对象引用。
  IL_0012:  ldloc.3   //把调用堆栈索引为3处的值复制到计算堆栈

  IL_0013:  box        [mscorlib]System.Int32     //装箱
  IL_0018:  call       string [mscorlib]System.String::Concat(object,object)   //调用内部方法
  IL_001d:  call       void [mscorlib]System.Console::WriteLine(string)       //调用WriteLine
  IL_0022:  nop       //无操作
  IL_0023:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()  //调用ConsoleKey
  IL_0028:  pop      //无操作
  IL_0029:  ret      //return
} // end of method Program::Main

四、最后

IL是跟我高级架构经理的分享和博客园相关的博客学习总结的,最后留2个题目,也是我的高级架构经理分享中提到的两个好玩的问题,也能看出对IL的掌握的程度

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/592700.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

让代码创造童话,共建快乐世界

六一儿童节即将到来,小朋友们开心的笑容弥漫了整个城市。对于大多数孩子来说,六一儿童节意味着玩具和糖果。但尽管这些看起来微不足道,却是他们幼小而纯真心灵的欢笑。而心怀童真的大人们则用他们手中的代码,创造出一个快乐而幸福…

CI858K01 3BSE018135R1 简化数据的编译

CI858K01 3BSE018135R1系列由以下部分组成: em4远程:完全连接到安全基础设施em4警报:能够发送短信或电子邮件警报em4本地:为不需要远程通信或只需要局域网的应用而设计 CI858K01 3BSE018135R1 remote的主要优势是可以连接到互联网,从而提供编程、监控和数据记录功…

怎么把图片转换成pdf格式?

怎么把图片转换成pdf格式?PDF 文件是一种非常流行的文件格式,几乎所有的电脑都自带了 PDF 阅读器工具。将图片转换成 PDF 格式后,在任何电脑或移动设备上,都能轻易地查看、共享和传输,兼容性更好。PDF 文件可以加密保护…

Zotero之多篇文献引用

前提 需看下我的这篇:Zotero文献在word中的引用 具体操作 Step01 在Word中引用多篇文献 点击“Add/Edit Citation”在跳出的Zotero搜索框中,选择“经典视图”在跳出的“添加/编辑引注”界面中,点击“多重来源”(单一来源&…

MFC (四) 处理文本

默认消息的处理方法 1.确认什么消息 2.添加消息处理函数 3.添加代码 默认消息指在消息定义中已存在的消息 这里我们对文本做换行处理 1.我们在ondraw里修改代码,这样,无论放大,缩小,都不会改变文本 void CMFCpaintView::On…

基于博客系统的测试

目录 1.测试用例 2.编写代码 2.1InitAndEnd 2.2BlogCases 编写测试用例 2.2.1.登录 2.2.2博客列表页 2.2.3写博客 2.2.4博客详情页校验 2.2.5写博客后,校验博客列表页 2.2.6删除刚才测试发布的博客 2.2.7注销 1.测试用例 2.编写代码 创建两个类 2.1InitAndEnd 用于…

【矩池云】YOLOv3~YOLOv5训练红外小目标数据集

一、数据集准备 数据集下载地址:https://github.com/YimianDai/sirst 1. 需要将数据集转换为YOLO所需要的txt格式 参考链接:https://github.com/pprp/voc2007_for_yolo_torch 1.1 检测图片及其xml文件 import os, shutildef checkPngXml(dir1, dir2…

OceanBase并行执行中 DTL消息接收处理的逻辑

OceanBase 并行执行的消息处理框架是很有意思的,里面用到了不少面向对象编程思想,值得分析。 DTL 从宏观上看可以分为三大部分: DTL 消息发送DTL 消息缓存DTL 消息处理 本文介绍 DTL 消息处理。 核心组件 DTL 消息缓冲区 DTL 消息缓冲区…

不懂这10个命令,别说你会调试网络设备

我的网工朋友大家好啊 好久没跟你们聊思科设备了。 虽然目前大方向上,企业用的设备越来越偏向国产化,学习华为、华三等厂商知识的人也越来越多。 但不可否认的是,思科仍然是厂商老大哥。 交换机、路由器这两块,思科占的全球市场…

若依框架请求magic-api接口出现Uncaught (in promise) error Promise.then (async)

错误描述: 在若依前端向magic-api发请求,实际上收到了返回的数据,但是仍出现错误提示。 错误截图: 猜测的原因: 请求参数错误返回参数错误magic-api内部语法错误 排除原因 在magic-api中仅返回一个数,同…

ChatGPT浪潮席卷,维智科技以时空AI赋能数实融合的未来城市

作者 | 伍杏玲 出品 | CSDN 每个时代都有新的技术浪潮,但在短短两年时间里见证两项颠覆全球的技术发展,实在出人意料之外:2021年以来,元宇宙成为互联网产业新风口,今年ChatGPT成为IT圈“顶流”,这两者为地…

Java访问QingCloud青云QingStor对象存储(公有云、私有云)

一、参考API 官网SDK文档参考:Java SDK - 公有云文档中心 (qingcloud.com) 二、环境说明 公有云跟私有云区别: 使用公有云QingStor,直接按照官网sdk直接可对接,私有云QingStor的话,需要设置具体的私有云请求地址及z…

chatgpt赋能python:Python中构造函数的名称

Python中构造函数的名称 作为一名有10年Python编程经验的工程师,我深知Python语言中构造函数的重要性。在本文中,我将着重介绍Python中构造函数的名称,并阐述其在Python编程中的作用。 什么是构造函数? 构造函数是一种特殊类型…

【C#学习记录】添加控件后工具箱不显示是什么原因

大家好,我是雷工! 今天在一个Winform程序中用到将WindowsMediaPlayer控件添加到工具箱,但添加了好几次,工具箱内均无法显示,经翻找资料和验证确认是跟创建项目时选择的模板有关,为了遇到同样问题的小伙伴能…

荣获用友年度十佳产业融合生态伙伴称号 | 图扑软件

2023 年 4 月 20 日,由中华全国工商业联合会联合工业和信息化部、国务院国资委组织开展的 2023 年度“百场万企”大中小企业融通对接活动——智能制造 MES 产业融通对接会暨 2023 用友 BIP 技术大会 MES 生态创新专题论坛在用友产业园顺利召开。 用友年度生态合作伙…

C语言学习分享(第九次)------数据的存储

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C语言学习分享⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习更多C语言知识   🔝🔝 数据的存储 1. 前言🚩2…

符合国情的supabase私有化部署(0)

符合国情的supabase私有化部署(0) 符合国情的supabase私有化部署(0) 前言开源 BaaS 解决方案快速开始 获取部署文件服务明细 容器启动后创建一个前端app注册邮箱SMTP协议jwt token和kong网关配置并应用更改数据库密码k8s 部署参考尾言常见问题 name resolution failedInvalid …

Python:Python编程:从入门到实践__超清版:Python标准库

Python标准库 1. OrderedDict2. threading三级目录 Python标准库是一组模块,按照的Python都包含了它,我们只需要在程序开头包含一条简单的 import 语句,就可以使用标准库中的任何函数和类。 下面我介绍几个重点 标准库 os : 提供一些与操作系…

Word控件Aspose.Words教程:使用 Java 处理 SXC 和 FODS 文件

Aspose.Words是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。 Aspose API支持流行文件格式处理,并…

NUC980编译错误,multiple target patterns(多个目标匹配)

1:问题: 昨天环境编译的还是没问题的,今天就出错了 : Makefile:133: *** multiple target patterns. Stop 此时:make make clean make disclean 都不可以使用了,报一样的错误。 2:解决办法&…