从编译指令中删除VS2015 stloc.0和ldloc.0 [英] VS2015 stloc.0 and ldloc.0 are removed from compilation instructions

查看:819
本文介绍了从编译指令中删除VS2015 stloc.0和ldloc.0的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Mono.Cecil.dll反编译一个VS 2015应用程序。
在反编译过程中,我注意到有两条指令(stloc.0& ldloc.0)缺失。
当我反编译一个VS 2013应用程序时没有发生。

I am using Mono.Cecil.dll to decompile a VS 2015 app. During decompilation I noticed that there are 2 instructions (stloc.0 & ldloc.0) that are missing. This did not happen when I decompiled a VS 2013 application.

反编译器或Visual Studio 2015编译器有问题吗?

Is there a problem with the decompiler or Visual Studio 2015 complier has changed?

更新:

我已使用ILDasm反编译代码。这里是在2015年和2013年在初始化组件中找到的。问题仍然出现:

I have decompiled the code using ILDasm. Here is what can be found in 2015 and 2013 in Initialize component. The problem still appears:

2015

.method private hidebysig instance void  InitializeComponent() cil managed
{
    // Code size       125 (0x7d)
    .maxstack  4
    IL_0000:  ldtoken    VS2015DotNet4test.Form1
    IL_0005:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
    IL_000a:  newobj     instance void [System]System.ComponentModel.ComponentResourceManager::.ctor(class [mscorlib]System.Type)
    IL_000f:  ldarg.0
    IL_0010:  newobj     instance void [System.Windows.Forms]System.Windows.Forms.Label::.ctor()
    IL_0015:  stfld      class [System.Windows.Forms]System.Windows.Forms.Label VS2015DotNet4test.Form1::label1
    IL_001a:  ldarg.0
    IL_001b:  call       instance void [System.Windows.Forms]System.Windows.Forms.Control::SuspendLayout()
    IL_0020:  dup
    IL_0021:  ldarg.0
    IL_0022:  ldfld      class [System.Windows.Forms]System.Windows.Forms.Label VS2015DotNet4test.Form1::label1
    IL_0027:  ldstr      "label1"
    IL_002c:  callvirt   instance void [System]System.ComponentModel.ComponentResourceManager::ApplyResources(object,
                                                                                                        string)
    IL_0031:  ldarg.0
    IL_0032:  ldfld      class [System.Windows.Forms]System.Windows.Forms.Label VS2015DotNet4test.Form1::label1
    IL_0037:  ldstr      "label1"
    IL_003c:  callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)
    IL_0041:  ldarg.0
    IL_0042:  ldstr      "$this"
    IL_0047:  callvirt   instance void [System]System.ComponentModel.ComponentResourceManager::ApplyResources(object,
                                                                                                        string)
    IL_004c:  ldarg.0
    IL_004d:  ldc.i4.1
    IL_004e:  call       instance void [System.Windows.Forms]System.Windows.Forms.ContainerControl::set_AutoScaleMode(valuetype [System.Windows.Forms]System.Windows.Forms.AutoScaleMode)
    IL_0053:  ldarg.0
    IL_0054:  call       instance class [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection [System.Windows.Forms]System.Windows.Forms.Control::get_Controls()
    IL_0059:  ldarg.0
    IL_005a:  ldfld      class [System.Windows.Forms]System.Windows.Forms.Label VS2015DotNet4test.Form1::label1
    IL_005f:  callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection::Add(class [System.Windows.Forms]System.Windows.Forms.Control)
    IL_0064:  ldarg.0
    IL_0065:  ldstr      "Form1"
    IL_006a:  call       instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)
    IL_006f:  ldarg.0
    IL_0070:  ldc.i4.0
    IL_0071:  call       instance void [System.Windows.Forms]System.Windows.Forms.Control::ResumeLayout(bool)
    IL_0076:  ldarg.0
    IL_0077:  call       instance void [System.Windows.Forms]System.Windows.Forms.Control::PerformLayout()
    IL_007c:  ret
} // end of method Form1::InitializeComponent

2013

.method private hidebysig instance void  InitializeComponent() cil managed
{
  // Code size       127 (0x7f)
  .maxstack  3
  .locals init (class [System]System.ComponentModel.ComponentResourceManager V_0)
  IL_0000:  ldtoken    VS2013DotNet4test.Form1
  IL_0005:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_000a:  newobj     instance void [System]System.ComponentModel.ComponentResourceManager::.ctor(class [mscorlib]System.Type)
  IL_000f:  stloc.0
  IL_0010:  ldarg.0
  IL_0011:  newobj     instance void [System.Windows.Forms]System.Windows.Forms.Label::.ctor()
  IL_0016:  stfld      class [System.Windows.Forms]System.Windows.Forms.Label VS2013DotNet4test.Form1::label1
  IL_001b:  ldarg.0
  IL_001c:  call       instance void [System.Windows.Forms]System.Windows.Forms.Control::SuspendLayout()
  IL_0021:  ldloc.0
  IL_0022:  ldarg.0
  IL_0023:  ldfld      class [System.Windows.Forms]System.Windows.Forms.Label VS2013DotNet4test.Form1::label1
  IL_0028:  ldstr      "label1"
  IL_002d:  callvirt   instance void [System]System.ComponentModel.ComponentResourceManager::ApplyResources(object,
                                                                                                        string)
  IL_0032:  ldarg.0
  IL_0033:  ldfld      class [System.Windows.Forms]System.Windows.Forms.Label VS2013DotNet4test.Form1::label1
  IL_0038:  ldstr      "label1"
  IL_003d:  callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)
  IL_0042:  ldloc.0
  IL_0043:  ldarg.0
  IL_0044:  ldstr      "$this"
  IL_0049:  callvirt   instance void [System]System.ComponentModel.ComponentResourceManager::ApplyResources(object,
                                                                                                        string)
  IL_004e:  ldarg.0
  IL_004f:  ldc.i4.1
  IL_0050:  call       instance void [System.Windows.Forms]System.Windows.Forms.ContainerControl::set_AutoScaleMode(valuetype [System.Windows.Forms]System.Windows.Forms.AutoScaleMode)
  IL_0055:  ldarg.0
  IL_0056:  call       instance class [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection [System.Windows.Forms]System.Windows.Forms.Control::get_Controls()
  IL_005b:  ldarg.0
  IL_005c:  ldfld      class [System.Windows.Forms]System.Windows.Forms.Label VS2013DotNet4test.Form1::label1
  IL_0061:  callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection::Add(class [System.Windows.Forms]System.Windows.Forms.Control)
  IL_0066:  ldarg.0
  IL_0067:  ldstr      "Form1"
  IL_006c:  call       instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)
  IL_0071:  ldarg.0
  IL_0072:  ldc.i4.0
  IL_0073:  call       instance void [System.Windows.Forms]System.Windows.Forms.Control::ResumeLayout(bool)
  IL_0078:  ldarg.0
  IL_0079:  call       instance void [System.Windows.Forms]System.Windows.Forms.Control::PerformLayout()
  IL_007e:  ret
} // end of method Form1::InitializeComponent


推荐答案

从我看来,这不应该产生任何可观察到的差异 - 这可能只是Roslyn是一个更聪明的编译器的结果。该值仍然在虚拟堆栈上,准备在需要时使用。没有必要将它存储在(虚拟)本地。

From what I see, this shouldn't make any observable difference - it's likely simply the result of Roslyn being a smarter compiler. The value is still on the virtual stack, ready to be used when needed. There's no need to store it in a (virtual) local.

VS2015编译器是全新的,从头开始构建,因此可以预期一些差异。

The VS2015 compiler is completely new, built from scratch, so some differences are to be expected.

请注意VS2013版本的 .maxstack 为3,与VS2015中的4相比 - 这是原因。 VS2013的编译器只保存了一个堆栈槽,而VS2015保存了一个本地槽(和一些指令)。

Note how the VS2013 version has .maxstack of 3, compared to 4 in VS2015 - this is the reason. VS2013's compiler simply saved one stack slot, while VS2015 saved one local slot (and a few instructions).

这个值在代码中使用了两次,与以不同的方式:VS2013保存在本地的值,需要时检索。 VS2015只是让值留在堆栈上,并且在它第一次使用之前, dup ped。

The value is used twice in the code, each of the compilations dealing with that in a different way: VS2013 saved the value in a local, to be retrieved when needed. VS2015 simply let the value stay on stack, and just before it's used for the first time, dupped it.

从JIT编译中查看生成的x86程序集 - 这两个程序甚至可能产生相同的代码,这是很有趣的,因为大多数优化发生在JIT级别,而不是C#编译本身。

It might be interesting to have a look at the resulting x86 assembly from the JIT compilation - the two might even produce identical code, since most of the optimizations happen on the JIT level, not the C# compilation itself.

编辑:

好吧,让我们仔细看看VS2015代码中的虚拟堆栈

Okay, let's have a closer look at the virtual stack in the VS2015 code (I'm simplifying for clarity):


  • 推荐表单 RuntimeHandle ,弹出并按类型(== typeof(Form)

  • 弹出键入,推动 new ResourceManager $ c> Type 参数

  • / code>,弹出以将标签存储在字段 this.label1

  • / strong>只需 ResourceManager

  • 再次按 Control.SuspendLayout (== this.SuspendLayout

  • dup 堆栈上的最后一个值( ResourceManager 实例)

  • c $ c> this ,push this.label1 (弹出 this ), code>label1

  • 当前堆栈 ResourceManager ResourceManager this.label1 label1 / li>
  • 调用 ApplyResources (它有三个参数,因此弹出最后三个)

  • Push Form as a RuntimeHandle, pop it and push the Type (== typeof(Form))
  • Pop Type, push new ResourceManager (takes the Type argument)
  • Push this, push new Label, pop both to store the label in the field this.label1
  • Current stack: just the ResourceManager
  • Push this again, and use it to call Control.SuspendLayout (== this.SuspendLayout)
  • dup the last value on stack (the ResourceManager instance)
  • Push this, push this.label1 (popping this), push "label1"
  • Current stack: ResourceManager, ResourceManager, this.label1, "label1"
  • Call ApplyResources (which takes three arguments, so pop the last three)

在这之后,我们仍然有 ResourceManager 在堆栈上,而不使用任何本地。

After all this, we still have the ResourceManager on stack, without using any local.

这篇关于从编译指令中删除VS2015 stloc.0和ldloc.0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆