Reflector中的Label_标记是从哪里来的,如何解码?

3

我正在尝试理解使用Reflector的反汇编功能的方法。像使用这个工具的任何人都会知道,某些代码显示为C#标签,这些标签(可能)没有在原始源中使用。

在我正在查看的110行方法中,有11个标签语句。随机片段示例:

Label_0076:
    if (enumerator.MoveNext())
    {
        goto Label_008F;
    }
    if (!base.IsValid)
    {
        return;
    }
    goto Label_0219;
Label_0087:
    num = 0;
    goto Label_01CB;
Label_01CB:
    if (num < entityArray.Length)
    {
        goto Label_0194;
    }
    goto Label_01AE;
Label_01F3:
    num++;
    goto Label_01CB;

什么样的代码可以使反射器在各处显示这些标签,为什么它不能对它们进行反汇编?

有没有一种好的技巧来解读它们?

2个回答

7
实际上,C#编译器并没有进行太多的优化 - 它把这个任务留给了JIT编译器(或者ngen)。因此,它生成的IL代码相当一致和可预测,这就是为什么像Reflector这样的工具能够如此有效地反编译IL。编译器转换您的代码的一个情况是在迭代器方法中。您正在查看的方法可能包含以下内容:
foreach(var x in something)
  if(x.IsValid)
    yield return x;

由于迭代器转换可能非常复杂,反编译器无法处理它。为了熟悉需要查找的内容,请编写自己的迭代器方法并将其运行通过反编译器以查看基于您的C#代码生成了什么类型的IL。然后您就会知道要查找什么。


3
你正在查看编译器生成的代码。编译器并不尊重你。真的。它也不尊重我或其他任何人。它看着我们的代码,嘲笑我们,并重新编写以使其尽可能高效地运行。
嵌套的if语句、递归、"yield"、case语句和其他代码快捷方式会导致代码看起来很奇怪。如果你使用带有许多封闭项的lambda函数,那么不要期望它看起来很漂亮。
只要有机会,编译器就会重写你的代码以使其运行更快。因此,并没有任何一种"代码类型"会导致这种情况。Reflector尽力反汇编,但它无法从重写的版本中推断出作者的原始代码。它尽力(有时甚至是错误的!)将IL翻译成某种可接受的代码形式。
如果你难以解密它,你可以手动编辑代码,将只调用一次的goto内联,将调用多次的goto重构为方法调用。另一种选择是反汇编为另一种语言。将IL转换为更高级别语言的代码并不相同。C++/CLI反编译器可能会为您做得更好,而且仍然足够相似(使用“.”替换“->”)以便理解。
对于这个问题,真的没有什么万能药;至少在有人编写一个更好的反汇编插件之前是这样的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接