翼度科技»论坛 编程开发 .net 查看内容

IL阅读第一篇,简单的加法

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
阅读IL主要是为了能够更好的学会Emit
从控制台开始吧:事先准备工具ILSpy,和IL的命令指南(这个可以网上搜索或者去看OpCode枚举),记住栈中的都是引用的地址
  1. int i = 10;
  2.             int j = 20;
  3.             int k = 30;
  4.             Console.WriteLine(i + j + k);
  5.             Console.ReadKey();
复制代码
编译后查看IL
  1.         .maxstack 2
  2.         .entrypoint
  3.         .locals init (
  4.                 [0] int32 i,
  5.                 [1] int32 j,
  6.                 [2] int32 k
  7.         )
  8.         IL_0000: nop
  9.         IL_0001: ldc.i4.s 10
  10.         IL_0003: stloc.0
  11.         IL_0004: ldc.i4.s 20
  12.         IL_0006: stloc.1
  13.         IL_0007: ldc.i4.s 30
  14.         IL_0009: stloc.2
  15.         IL_000a: ldloc.0
  16.         IL_000b: ldloc.1
  17.         IL_000c: add
  18.         IL_000d: ldloc.2
  19.         IL_000e: add
  20.         IL_000f: call void [mscorlib]System.Console::WriteLine(int32)
  21.         IL_0014: nop
  22.         IL_0015: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  23.         IL_001a: pop
  24.         IL_001b: ret
复制代码
  解释如下:
第一段:
     .maxstack 2
    .entrypoint
    .locals init (
        [0] int32 i,
        [1] int32 j,
        [2] int32 k
    )
这段代码是定义一个深度为2的栈,然后初始化三个变量都内存
第二段:
     IL_0000: nop
    IL_0001: ldc.i4.s 10
    IL_0003: stloc.0
    IL_0004: ldc.i4.s 20
    IL_0006: stloc.1
    IL_0007: ldc.i4.s 30
    IL_0009: stloc.2
这段代码nop是:如果修补操作码,则填充空间。尽管可能消耗处理周期,但未执行任何有意义的操作。(我想,这也许就是可以优化掉的)
然后ldc.i4.s:将提供的 int8 值作为 int32 推送到计算堆栈上(短格式)。大致就是将一个静态的数值推送到计算堆栈上,这里是将10推送上去,压入栈中。
接着stloc.0:从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。在栈顶部弹出10到变量中。
一下20和30都是同上。
第三段:
    IL_000a: ldloc.0
    IL_000b: ldloc.1
    IL_000c: add
    IL_000d: ldloc.2
    IL_000e: add
这段代码ldloc.0:将索引 0 处的局部变量加载到计算堆栈上。
意思是压入第一个变量到栈,压入第二个变量到栈,然后执行add操作。add操作是将栈顶部前两个弹出执行,再将得到的数压入栈。
然后就是索引三,也就是第三个变量压入到栈,接着在执行add,将结果压入栈。现在为止,栈中只有一个量。
第四段:
 IL_000f: call void [mscorlib]System.Console::WriteLine(int32)
 IL_0014: nop
弹出栈的第一个量,执行System.Console下的WriteLine函数,
第五段:
     IL_0015: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
    IL_001a: pop
ReadKey()没有参数,直接执行。
第六段:
 IL_001b: ret
ret:从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。

来源:https://www.cnblogs.com/RainbowInTheSky/archive/2023/04/03/4569128.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具