【问题标题】:VS2015 stloc.0 and ldloc.0 are removed from compilation instructionsVS2015 stloc.0 和 ldloc.0 从编译指令中去掉
【发布时间】:2015-09-23 08:07:40
【问题描述】:

我正在使用 Mono.Cecil.dll 反编译 VS 2015 应用程序。 在反编译期间,我注意到缺少 2 条指令(stloc.0 和 ldloc.0)。 当我反编译一个 VS 2013 应用程序时,这并没有发生。

是反编译器有问题还是Visual Studio 2015编译器改了?

更新:

我已经使用 ILDasm 反编译了代码。这是 2015 年和 2013 年可以在 Initialize 组件中找到的内容。问题依旧出现:

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

【问题讨论】:

  • 您可以将代码复制为文本并粘贴吗?
  • 我怀疑也不需要这么多代码。最好展示一下:a)C#; b) VS2013生成的IL; c) 2015 年生成的 IL。还要注意您正在使用的选项(例如调试或发布版本)。

标签: .net compiler-construction mono visual-studio-2015


【解决方案1】:

据我所知,这不应该产生任何明显的差异——这可能只是 Roslyn 是一个更智能的编译器的结果。该值仍在虚拟堆栈上,可以在需要时使用。无需将其存储在(虚拟)本地。

VS2015 编译器是全新的,从头开始构建,因此会出现一些差异。

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

该值在代码中使用了两次,每次编译都以不同的方式处理该值:VS2013 将值保存在本地,以便在需要时检索。 VS2015 只是让值留在堆栈上,在第一次使用它之前,dupped 它。

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

编辑:

好的,让我们仔细看看VS2015代码中的虚拟堆栈(为了清楚起见,我正在简化):

  • Form 推送为RuntimeHandle,弹出并推送Type (== typeof(Form))
  • 弹出Type,推送new ResourceManager(接受Type 参数)
  • this,推new Label,同时弹出以将标签存储在this.label1字段中
  • 当前堆栈: 只是 ResourceManager
  • 再次推送this,并用它调用Control.SuspendLayout(== this.SuspendLayout
  • dup 堆栈上的最后一个值(ResourceManager 实例)
  • this,推this.label1(弹出this),推"label1"
  • 当前堆栈: ResourceManager, ResourceManager, this.label1, "label1"
  • 调用ApplyResources(需要三个参数,所以弹出最后三个)

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

【讨论】:

  • 问题是我需要解析指令列表以便从中获取资源,这意味着我必须以某种方式找出进行了哪些修改。
  • @Mihai 好吧,这与当地人无关,是吗?新代码中有什么东西会破坏您的分析吗?您是否认为资源管理器必须分配给本地?
  • 基于 IL 指令,我正在创建一个块语句的“堆栈”,这是根据我对您所说的虚拟堆栈的理解。问题是,在 VS2013 ldloc.0 中,基于 ComponentResourceManager V_0 初始化将一个局部变量推送到堆栈上,但 dup 复制了堆栈上的最后一个值,在我的情况下这是一条指令 SuspendLayout()。我们所说的只有一个堆栈,还是这些值也存储在其他地方? dup 从哪里检索值?无需优化代码,它就可以工作。生成的代码与 2013 年相同,使用 ldloc 和 stloc。
  • @Mihai 我认为你的方法只是偶然的,真的。局部变量是一个简单的有序数组,dup 复制堆栈上的最后一个值 - 不是 SuspendLayout,因为SuspendLayout 不返回值。虚拟堆栈只包含值/引用,不包含返回地址或任何东西。为了正确解释它,你需要知道每个方法调用的输入和输出参数——一旦你知道了,实现起来就很简单了。一个接一个地执行,你会看到资源管理器实际上是dupped。
  • @Mihai 我在视图中编辑了虚拟堆栈上发生的情况。也许这会让你在这里想错了什么更清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 2016-05-27
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
相关资源
最近更新 更多