22

今天我在VS2008提供的工具之间找到了Disassembler IL。我试图反汇编一个程序并查看结果。操作码并不难理解,但有一件事让我感到惊讶:.NET 是基于堆栈的?!阅读“编写出色的代码,第二卷”时,我没有很好地了解基于堆栈的机器,因为它们非常慢。它们也很容易实现,但我不认为 MS 开发人员选择这种方法是因为它简单,毕竟代码必须被翻译成真正的机器代码,这样他们才能解决问题。
你们中的任何人都可以解释这个奇怪的选择吗?

PS
我在这里发布我读到的关于这个主题的内容:

13.1.1 基于堆栈的机器 基于 堆栈的机器使用内存进行大多数计算,在内存中使用堆栈来保存所有操作数和结果。与其他架构相比,采用堆栈架构的计算机系统具有一些重要优势:

  • 这些指令通常比其他体系结构中的指令更小(每条指令消耗更少的字节),因为指令通常不必指定任何操作数。
  • 为堆栈架构编写编译器通常比为其他机器更容易,因为将算术表达式转换为一系列堆栈操作非常容易。
  • 在堆栈架构中很少需要临时变量,因为堆栈本身就是为这个目的服务的。
不幸的是,堆栈机器也有一些严重的缺点:
  • 几乎每条指令都引用内存(这在现代机器上很慢)。尽管缓存可以帮助缓解这个问题,但内存性能仍然是堆栈机器上的主要问题。
  • 尽管从 HLL 到堆栈机器的转换非常容易,但与其他架构相比,优化的机会更少。
  • 因为堆栈机器不断地访问相同的数据元素(即堆栈顶部的数据),所以很难实现流水线和指令并行(有关流水线和指令并行的详细信息,请参见编写出色的代码,第 1 卷)。
堆栈是一种数据结构,它只允许对堆栈的少数有限元素(通常称为堆栈顶部和堆栈上的下一个)进行操作。对于堆栈,您通常会做以下三件事之一:将新数据压入堆栈,从堆栈中弹出数据,或对当前位于堆栈顶部的数据(可能还有紧接其下方的数据)进行操作。

13.1.1.5 现实世界的堆栈机器
堆栈架构的一大优点是很容易为这样的机器编写编译器。为基于堆栈的机器编写模拟器也很容易。由于这些原因,堆栈架构在虚拟机 (VM) 中很流行,例如 Java 虚拟机和 Microsoft Visual Basic p-code 解释器。一些现实世界中基于堆栈的 CPU 确实存在,例如 Java VM 的硬件实现;但是,由于内存访问的性能限制,它们并不是很受欢迎。尽管如此,了解堆栈架构的基础知识还是很重要的,因为许多编译器在翻译成实际机器代码之前会将 HLL 源代码翻译成基于堆栈的形式。事实上,在最坏的情况下(虽然很少见),

编辑:我刚刚在@EricLippert 的博客中找到了一篇文章,回答了这个问题并确认了@Aaron 的回答

4

3 回答 3

18

请记住,仅仅因为中间表示是基于堆栈的,并不意味着生成的机器代码是基于堆栈的。当代码从中间形式转换为机器代码时,它基本上是重新编译的——允许本地优化。

使用基于堆栈的中间表示的好处曾经是您不受任何特定架构的束缚。

想象一下,如果他们决定使用基于寄存器的理论系统作为他们的中间形式。他们应该选择多少个寄存器?8?16?64?如果您的目标处理器具有比中间形式更多的实际寄存器,那么您就失去了可能的优化。如果您的目标的实际寄存器比中间寄存器少,那么您的优化会适得其反,因为这些寄存器无论如何都会刷新到内存中。

即使在当前的 CPU 上,编译到 x86 和 x64 也有很大的不同——更不用说替代架构 (ARM) 或未来的架构了。

对于这样的事情,最好将其保持为最简单的形式,然后在最终代码生成期间依赖优化以使其与实际硬件相匹配。

于 2011-05-09T18:07:25.480 回答
1

CIL 之所以基于堆栈,是因为它并非设计为针对 VM 的指令集。这是编译的中间阶段。

CLR 更像是一个编译器+运行时,而不是像 JVM 这样的虚拟机。CLR 设计并不试图提供解释字节码的良好性能。相反,它尝试在运行时检查高级字节码并将其编译为机器码。

于 2011-05-09T18:41:46.153 回答
0

您将不得不询问 Microsoft 开发人员。但我猜性能问题不是他们的第一关注点。大多数 Windows 应用程序不受 CPU 限制,甚至不受 I/O 限制,因为它们大部分时间都在等待用户单击按钮。然而,拥有一个允许他们轻松实现新语言的架构可能是一个优先事项。

于 2011-05-09T17:46:23.387 回答