MSIL语法笔记

     .net core的JIT编译分前端和后端。前端负责把IL指令转换到JIT的高级中间表现HIR。后端负责把HIR转换到低级中间表现LIR后,再转换到架构相关的汇编指令。结构如图:

.netcore 流程

 

       逆向.net程序(.dll .exe)到IL的工具有ildasm、ILSpy、dnSpy。其中ildasm为官方提供工具,在源码coreclr中生成,可以把.net程序转换到IL代码。与ildasm对应的还有个ilasm工具,可以把IL代码再转换成.net程序集。ILSpy和dnSpy不仅能把.net程序转换到IL代码,还能转换到c#/f#等IL之前的高级语言。

本文只关注JIT编译前的IL指令格式。

 

一、IL指令

      JIT之前的MSIL(Microsoft Intermediate Language 简称:IL),.Net 框架使用的中间件语言。IL语言很像汇编语言(比如MIPS),有栈空间、load/store指令、运算指令等。IL中的栈叫评价堆栈,用于在指令间传递临数据。IL中的评价堆栈原理很像逆波兰式记法(Reverse Polish Notation)。常用IL指令如下表。

 

功能
Ldc_I4_0

将整数值 0 作为 int32 推送到计算堆栈上。

Stloc_0

从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。

Br

 无条件地将控制转移到目标指令。

Brtrue

如果 valuetrue、非空或非零,则将控制转移到目标指令。

Break

向公共语言结构 (CLI) 发出信号以通知调试器已撞上了一个断点。

Add

将两个值相加并将结果推送到计算堆栈上。

Sub

从其他值中减去一个值并将结果推送到计算堆栈上。

Mul

将两个值相乘并将结果推送到计算堆栈上。

Div

将两个值相除并将结果作为浮点(F 类型)或商(int32 类型)推送到计算堆栈上。

And

计算两个值的按位“与”并将结果推送到计算堆栈上。

Or

计算位于堆栈顶部的两个整数值的按位求补并将结果推送到计算堆栈上。

Neg

对一个值执行求反并将结果推送到计算堆栈上。

Nop

如果修补操作码,则填充空间。 尽管可能消耗处理周期,但未执行任何有意义的操作。

Ldloc

将指定索引处的局部变量加载到计算堆栈上。

Clt

比较两个值。 如果第一个值小于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。

Call

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

Ret

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

Throw

引发当前位于计算堆栈上的异常对象。

Volatile

指定当前位于计算堆栈顶部的地址可以是易失的,并且读取该位置的结果不能被缓存,或者对该地址的多个存储区不能被取消。

   如果你熟悉某一种体系架构,比如ARM、MIPS、X64。那么在理解上表列举的IL指令会特别的轻松。上表也仅仅列举了IL指令的一部分。更详细语法参看官方 https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.emit.opcodes?view=netcore-3.0

二、示例

下面通过一个小的例子来简单了解一下IL。首先编写一个c#程序

       static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }

上面这个C#程序,对应的IL代码如下(使用ildasm生成):

  .method private hidebysig static void  Main(string[] args) cil managed
  {
    .entrypoint 
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "Hello World!"
    IL_0006:  call       void [System.Console]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
  } // end of method Program::Main

下面分别介绍上述IL中每条语句:

  • .entrypoint   表示这个方法是主方法
  • .maxstack   表示该方法使用的评价堆栈的大小
  • nop              空指令什么都不做。d对应MIPS汇编指令中的nop ?
  • ldstr             将后面字符串“Hello World!” 存储到评价堆栈(入栈)
  • call              函数调用 System.Console::WriteLine(string),参数是栈顶值,即为“Hello World!”
  • ret                方法返回

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海棠花败

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值