如何正确反汇编.NET代码?
我试图反汇编我的C#代码,然后在汇编语言级别进行调试。 比方说,我们有一个简单的C#方法:如何正确反汇编.NET代码?
var a = 1235;
var b = ++a;
var c = ++b;
Console.WriteLine("test");
Console.ReadKey();
我发现了两种不同的方式如何获取汇编代码。 第一个是在VS中启动C#代码调试,然后打开Disassembly窗口。这里我们有以下代码。
一切行和汇编代码是非常简单和短,但问题是,这个汇编代码逻辑由ILDASM产生的IL代码的逻辑是不同的。
因此,这里是第二种方式。我们可以编译C#代码,使用ILDASM获得从PE文件中的IL代码,然后用ILASM生成PE文件恢复。现在我们有以下汇编代码。
正如你可以看到这个汇编代码更像是IL代码,但它包含更多的指令,这是更为复杂。
AFAIK C#编译为CIL代码,然后在这两种情况下的汇编代码。但它似乎是以第一种方式编译为汇编代码。
所以,问题是为什么第一方法的汇编代码从IL代码不同?为什么第一种方法的汇编代码与第二种方法的汇编代码不同?
的JIT能够重新排序和合并的机器指令作为optomisation,但会尽量避免移动由PDB提供跨sequence points的影响。编译器通常会为每行代码生成一个序列点,因为您通常一次一行地遍历它。
虽然C#往往会产生每行代码多个IL指令,ILASM被明确给定每个指令并这样生成更多的序列点,留下用于JIT优化的空间更小。
这个答案不是很准确,PDB文件肯定与序列点无关。 “代码行”也不是。代码提升和子表达式消除是JIT优化器知道也适用的标准优化器技术。 Backgrounder post [在这里](https://*.com/a/4045073/17034)。 –
@HansPassant,我想你可能会把PDB的序列点概念和C++概念混淆在同一个名字中。 pdb使用术语“序列点”来描述[IL 源映射](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/diagnostics/isymunmanagedmethod-getsequencepoints-method)。这个想法是,一个调试器很可能会停止在一个“序列点”的开始处,所以JIT会尝试使这些事情看起来一致(除非通过我链接到的文章中描述的DebuggableAttribute标志来告知其他事项在答案中。) –
感谢您的教训,从未见过这个术语的用法。未来的读者可能想知道,优化器不会尝试保持PDB信息的相关性。使用默认的项目配置,PDB甚至不包含任何行号信息。 –
CLR是一个虚拟机,因此代码的区别。类似于Java的JVM。 – t0mm13b
这是调试模式的代码(你可能有“禁止对模块加载JIT优化”打开),这样不是很有趣,但奇怪的是,这取决于它是否已经通过反汇编/ ILASM往返走了是不同的。 – harold
这不是一个“问题”,它是一个功能。在使用Release版本并关闭Suppress JIT优化选项时,仅查看机器代码是明智的。 –