【转载】读懂IL代码就这么简单(二)

【转载】读懂IL代码就这么简单(二)

一 前言

  IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致。个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 。感谢 @冰麟轻武 的指点

你没有看第一篇?  点这里看第一篇 读懂IL代码就这么简单(一)

IL指令大全 :IL指令详解

IL反编译工具: ILDasm

知识点回顾:

Managed Heap(托管堆):用于存放引用类型的值

Evaluation Statck(计算栈):临时存放值类型数据,引用类型地址的堆栈(这个是栈,所以遵循栈的操作特点,先进后出)

Call Stack(调用栈):其中的Record Frame 用于存放.locals init(int32 V_0)指令的参数值如:V_0 (Record Frame是一个局部变量表,所以不遵守FILO原则 )

二 指令详解(基本介绍)

2.1 知识点介绍

  在第一篇时,我只详细的写了值类型的IL指令,这一篇会主要以引用类型为主,这一篇会有装箱操作,所以先写一下装箱操作在内存中是如何操作的

装箱操作:1 内存分配,在托管堆中分配内存空间,2 将值类型的字段拷贝到新分配的内存中,3 将托管堆中的对象地址返回给新的对象

操作过程如下图

<span>【转载】读懂IL代码就这么简单(二)</span>

C#代码 

          /*
           Author:zery-zhang
           BlogAddress:http://www.cnblogs.com/zery/
           */
          static void Main(string[] args)
          {
              string name = "Zery";
              int age = 22;
              Console.WriteLine(age.ToString() + name);//已ToString的操作
              Console.WriteLine(age+name);//未ToString操作
  
          }

IL代码

     /*
          Author:zery-zhang
          BlogAddress:http://www.cnblogs.com/zery/
      */
      .method private hidebysig static void  Main(string[] args) cil managed
  {
    .entrypoint
    // Code size       48 (0x30)
  
   //以下代码 完成 C#代码中初始化变量的操作
  
    //计算栈(Evaluation Stack) 可容纳数据项的最大个数
    .maxstack  2              
     //定义并初始化参数 并存入 局部变量表(Record Frame)中
    .locals init (string V_0,int32 V_1) 
    IL_0000:  nop
    //把字符串压入计算栈(Evaluation Stack)中
    IL_0001:  ldstr      "Zery"   
    // 从计算栈中弹出("Zery")字符,并赋值给局部变量表中第0个位置的元素V_0
    IL_0006:  stloc.0       
    //把整数22压入计算栈中  
    IL_0007:  ldc.i4.s   22    
    //把整数22弹出,并赋值给局部变量表中第1个位置的元素V_1
    IL_0009:  stloc.1             
  
    //以下代码完成C#中的输出操作
  
    //取出局部变量表中V_1元素的值 "22" (copy)并压入计算栈中
    IL_000a:  ldloca.s   V_1 
    //弹出刚刚压入的值("22")调用ToString方法转成string类型并将引用存入计算栈中
    IL_000c:  call       instance string [mscorlib]System.Int32::ToString() 
     //取出局部变量表中第0个位置元素(V_0)的值("Zery")压入计算栈中(此时计算栈中有两个值,指向推管堆中"22"的引用地址和字符串"Zery")
    IL_0011:  ldloc.0            
     //弹出计算栈中两个值调用String的Concat方法把字个字符拼接存入托管堆中(Managed Heap )并返回地址压入计算栈中
    IL_0012:  call       string [mscorlib]System.String::Concat(string,string)   
     //调用输出方法,调用输出方法后计算栈中的值(指向托管堆字符的地址)会被回收 。
    IL_0017:  call       void [mscorlib]System.Console::WriteLine(string) 
  
    //未ToString的操作
    IL_001c:  nop
     //取局部变量表中第1个位置的元素V_1的值("22") 压入计算栈中
    IL_001d:  ldloc.1              
     //把刚刚压入的整数22 装箱并返回指向托管堆的地址存入计算栈中
    IL_001e:  box        [mscorlib]System.Int32   
     //取局部变量表中第0个位置的f元素V_0的值("Zery")并压入计算栈中
    IL_0023:  ldloc.0              
     //弹出计算栈中两个值调用String的Concat方法把字个字符拼接存入托管堆中(Managed Heap )并返回地址压入计算栈中
    IL_0024:  call       string [mscorlib]System.String::Concat(object,object)   
     //调用输出方法
    IL_0029:  call       void [mscorlib]System.Console::WriteLine(string)        
    IL_002e:  nop
     //标记返回
    IL_002f:  ret               
  } // end of method Program::Main

2.2 IL指令详解

  .maxstack:计算栈(Evaluation Stack)可容纳数据项的最大个数

  .locals init (int32 V_0,int32  V_1,int32 V_2):定义变量并存入Call Stack中的Record Frame中

  nop:即No Operation 没有任何操作,我们也不用管它,

  ldstr.:即Load String 把字符串加压入Evaluation Stack中 

  stloc.:把Evaluation Stack中的值弹出赋值到Call Stack中的Record Frame中

  ldloc.:把Call Stack里的Record Frame中指定位置的值取出(copy)存入 Evaluation Stack中   以上两条指令为相互的操作stloc赋值,ldloc取值

  call:  调用指定的方法

  box:执行装箱操作

  ret: 即return  标记返回

三 指令详解(深入介绍)

如果看代码中的注释你还不是很理解,那就看看下面的图解过程吧,如果每一步都画图,那工程太大了,所以我会把简单的的步组合成一张图并做上注释

先画初始化的代码详解图  注:为了减少图片所以栈的弹出与压入操作就省去了,都只画出了结果

IL_0001: ldstr “Zery”
IL_0006: stloc.0
IL_0007: ldc.i4.s 22
IL_0009: stloc.1

因为字符串是引用类型,所以是保存在托管堆中,而栈中只保存对字符引用的地址,可以看到图中的字符串是在托管中的,而计算栈中只保存了引用

<span>【转载】读懂IL代码就这么简单(二)</span>

IL_000a: ldloca.s V_1
IL_000c: call instance string [mscorlib]System.Int32::ToString()
IL_0011: ldloc.0
IL_0012: call string [mscorlib]System.String::Concat(string,string)
IL_0017: call void [mscorlib]System.Console::WriteLine(string)

<span>【转载】读懂IL代码就这么简单(二)</span>

IL_001d: ldloc.1
IL_001e: box [mscorlib]System.Int32
IL_0023: ldloc.0
IL_0024: call string [mscorlib]System.String::Concat(object,
object)
IL_0029: call void [mscorlib]System.Console::WriteLine(string)

装箱的过程图在上面已给出此处只把结果画出

<span>【转载】读懂IL代码就这么简单(二)</span>

四 总结

  1 用两篇把 值类型与引用类型在内存中不同的位置与不同的操作详细的写了,我觉得还是很有必要的,因为所有的数据类型由这两种类型组成,把这两种类型的操作了解了

看其它IL指令就是透过本质看现象了。

     2  关于画图,我觉得画图是程序员必学的知识,牛X的程序员画出来的,系统架构图,系统设计图等都是很有结构很清晰的。我的画图技能还有太多不足,只是画这种简单的图都觉得,无法完美的表达自己头脑所想的那样。

 

【转自】http://www.cnblogs.com/zery/p/3376973.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119352.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 一篇文章,教你彻底搞懂selenium的工作原理

    一篇文章,教你彻底搞懂selenium的工作原理

    2021年5月24日
    213
  • php将字符串内的指定字符全部替换,php中如何替换字符串中的某个字符[通俗易懂]

    php将字符串内的指定字符全部替换,php中如何替换字符串中的某个字符[通俗易懂]在PHP中,可以使用strtr()函数实现字符串替换。首先我们简单了解下strtr()函数的定义及语法。语法:stringstrtr(string$str,string$from,string$to)第一个参数表示待转换的字符串。第二个参数表示字符串中与将要被转换的目的字符to相对应的源字符。第三个参数表示字符串中与将要被转换的字符from相对应的目的字符。实例:…

    2022年5月23日
    36
  • ods mysql_ODS数据抽取平台[通俗易懂]

    ods mysql_ODS数据抽取平台[通俗易懂]一、产品简介ODS数据抽取平台是数据仓库对数据进行精细加工的中间环节,将加工后的数据存储到ODS数据模型中,以便总账,报表,数据仓库使用。将远程网络生产数据库中的数据备份到一台备份机中(防止对生产数据的误操作),然后在可视化的第三方ETL工具中编辑ETL脚本,对备份库中的数据进行精细的加工,ETL脚本可以对网络中的任意一台数据库中任意的一张或多张表进行复杂的计算,然后将计算结果保存到ODS的数据模…

    2022年9月26日
    4
  • 几种tree命令的简单安装方法

    几种tree命令的简单安装方法Linux基础tree命令的安装tree命令以树状图列出文件目录结构。不过某些Linux上(Centos6)没有tree命令,本文将介绍安装方法。一、利用镜像安装安装tree命令步骤1.查看系统版本:cat/etc/issue//查看发行版本2.将对应镜像放入光驱,3.挂载镜像文件mount/dev/cd

    2022年7月24日
    12
  • 基于B样条曲线的路径规划(含matlab代码免费下载)[通俗易懂]

    基于B样条曲线的路径规划(含matlab代码免费下载)[通俗易懂]本文主要解决的是用B样条曲线实现无人车的路径规划,对于B样条曲线的概念不再赘述,有兴趣的朋友可以自行去了解。下面介绍如何利用B样条曲线对小车进行路径规划。1.无人车平面曲线规划1.1无人车位置控制我们一般假设无人车只移动在平地或者类平面场地,跟着我们期望的曲线运动。原理设点的坐标为(xd,yd),则可得到θd的表达式为那么在实际应用中,我们如何生成一条期望曲线并让小车跟随它运动呢?1.2小车移库问题我们在生活中最常见的就是小车移库问题,这也是无人车类比赛中最基础的一类题目。因为小车

    2022年6月18日
    29
  • 阿里云申请免费ssl证书及安装_阿里云服务器升级配置

    阿里云申请免费ssl证书及安装_阿里云服务器升级配置阿里云购买免费SSL证书1.操作环境2.购买免费SSL证书3.证书申请,绑定域名《下一篇:Nginx+SSL证书,配置https》1.操作环境阿里云(已实名的企业账号)2.购买免费SSL证书2.1.如图,阿里云官网登陆后,搜索框内输入SSL,点击证书控制台,进入后点击购买证书2.2.如图,选中单域名–DVSSL–免费版,点击立即购买2.3.如图,勾选阅读,点击支付,在支付成功界面,点击证书控制台3.证书申请,绑定域名3.1.如图,在证书控制台,点击证书申请

    2022年10月3日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号