什么是堆的目的是什么?我们为什么需要它? [英] What is the purpose of a stack? Why do we need it?

查看:247
本文介绍了什么是堆的目的是什么?我们为什么需要它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我学习MSIL,现在要学会调试我的C#.NET应用程序

So I am learning MSIL right now to learn to debug my C# .NET applications.

我一直在想:是什么的目的?堆栈

只是把我的问题在上下文中:

为什么会出现从内存转移到堆叠或装?
在另一方面,为什么会出现转移,从堆栈存储器或保存?
为什么不把它们都放在内存?

Just to put my question in context:
Why is there a transfer from memory to stack or "loading?" On the other hand, why is there a transfer from stack to memory or "storing"? Why not just have them all placed in the memory?


  • 是不是因为它的速度更快?因为它是基于RAM

  • 是吗?

  • 为了提高效率?

我试图抓住这个帮助我了解 CIL 代码更加深刻。

I'm trying to grasp this to help me understand CIL codes much more deeply.

推荐答案

更新:我很喜欢这个问题这么多,我做它的我的博客/b/ericlippert/archive/2011/11/18/why-il.aspx\">the主题。感谢伟大的问题。

UPDATE: I liked this question so much I made it the subject of my blog on November 18th 2011. Thanks for the great question!

我一直想知道:什么是堆栈的目的是什么?

I've always wondered: what is the purpose of the stack?

我假设你的意思是的计算堆栈的的MSIL语言,而不是实际的每个线程栈在运行时。

I assume you mean the evaluation stack of the MSIL language, and not the actual per-thread stack at runtime.

为什么会出现从内存转移到堆叠或装?在另一方面,为什么会出现转移,从堆栈存储器或保存?为什么不把它们都放在内存?

Why is there a transfer from memory to stack or "loading?" On the other hand, why is there a transfer from stack to memory or "storing"? Why not just have them all placed in the memory?

MSIL是一个虚拟机的语言。像C#编译器编译器生成 CIL ,然后在运行时被称为JIT(准时),另一种编译器编译轮番IL为实际的机器代码可以执行。

MSIL is a "virtual machine" language. Compilers like the C# compiler generate CIL, and then at runtime another compiler called the JIT (Just In Time) compiler turns the IL into actual machine code that can execute.

所以,首先让我们来回答这个问题:为什么会有MSIL呢?为什么不只是有C#编译器写出来的机器代码?

So first let's answer the question "why have MSIL at all?" Why not just have the C# compiler write out machine code?

由于它的便宜的做这样的。假如我们没有这样做的;假设每一种语言都必须有它自己的机器代码生成器。你有20种不同的语言:C#,的JScript .NET ,Visual Basic中的IronPython F# ......而假设你有十个不同的处理器。有多少代码生成器,你必须写? 20×10 = 200代码生成器。这是一个很大的工作。现在假设你想添加一个新的处理器。你必须写为它二十次,每个语言的代码生成器。

Because it is cheaper to do it this way. Suppose we didn't do it that way; suppose each language has to have its own machine code generator. You have twenty different languages: C#, JScript .NET, Visual Basic, IronPython, F#... And suppose you have ten different processors. How many code generators do you have to write? 20 x 10 = 200 code generators. That's a lot of work. Now suppose you want to add a new processor. You have to write the code generator for it twenty times, one for each language.

此外,它是困难和危险的工作。编写高效的代码生成器,你是不是专家的芯片是一个艰苦的工作!编译器设计者们对他们的语言的语义分析,而不是新的芯片组有效的寄存器分配方面的专家。

Furthermore, it is difficult and dangerous work. Writing efficient code generators for chips that you are not an expert on is a hard job! Compiler designers are experts on the semantic analysis of their language, not on efficient register allocation of new chip sets.

现在假设我们做了CIL方式。多少CIL发电机你有写?每一种语言。多少的JIT编译器,你必须写?其中每个处理器。总计:20 + 10 = 30代码生成器。此外,语言对CIL发电机是很容易写,因为CIL是一种简单的语言,和CIL到机器代码生成器也很容易写,因为CIL是一种简单的语言。我们摆脱所有的C#和VB和诸如此类的东西和下一切以一种简单的语言,很容易写一个抖动的复杂的。

Now suppose we do it the CIL way. How many CIL generators do you have to write? One per language. How many JIT compilers do you have to write? One per processor. Total: 20 + 10 = 30 code generators. Moreover, the language-to-CIL generator is easy to write because CIL is a simple language, and the CIL-to-machine-code generator is also easy to write because CIL is a simple language. We get rid of all of the intricacies of C# and VB and whatnot and "lower" everything to a simple language that is easy to write a jitter for.

具有中等语言降低生产一种新的语言的编译器的的成本显着的。它还降低的极大支持新的芯片的成本。要支持一个新的芯片,你会发现芯片上的一些专家,并让他们写一个CIL抖动就完成了;然后你支持你的芯片上所有的语言

Having an intermediate language lowers the cost of producing a new language compiler dramatically. It also lowers the cost of supporting a new chip dramatically. You want to support a new chip, you find some experts on that chip and have them write an CIL jitter and you're done; you then support all those languages on your chip.

好了,我们已经建立了我们为什么MSIL;因为具有中间语言降低成本。那么,为什么是语言堆栈机?

OK, so we've established why we have MSIL; because having an intermediate language lowers costs. Why then is the language a "stack machine"?

由于堆机在概念上很简单的语言编译器的编写者来处理。堆栈是用于描述计算简单,易于理解的机制。堆栈机也从概念上很容易JIT编译器编写者来处理。使用栈是一个简化的抽象,因此再次的它降低了我们的成本

Because stack machines are conceptually very simple for language compiler writers to deal with. Stacks are a simple, easily understood mechanism for describing computations. Stack machines are also conceptually very easy for JIT compiler writers to deal with. Using a stack is a simplifying abstraction, and therefore again, it lowers our costs.

您问为什么有一个堆栈呢?为什么不直接做的一切直接内存不足?好吧,让我们想想这一点。假设你想生成CIL代码:

You ask "why have a stack at all?" Why not just do everything directly out of memory? Well, let's think about that. Suppose you want to generate CIL code for:

int x = A() + B() + C() + 10;



假设我们有约定的添加,打电话,店等方面始终拿他们的论点从堆栈把他们的结果(如果有)在堆栈中。要生成此C#CIL代码,我们只说是这样的:

Suppose we have the convention that "add", "call", "store" and so on always take their arguments off the stack and put their result (if there is one) on the stack. To generate CIL code for this C# we just say something like:

load the address of x // The stack now contains address of x
call A()              // The stack contains address of x and result of A()
call B()              // Address of x, result of A(), result of B()
add                   // Address of x, result of A() + B()
call C()              // Address of x, result of A() + B(), result of C()
add                   // Address of x, result of A() + B() + C()
load 10               // Address of x, result of A() + B() + C(), 10
add                   // Address of x, result of A() + B() + C() + 10
store in address      // The result is now stored in x, and the stack is empty.

现在假设我们做到了没有一个堆栈。我们会做你的方式,其中的每一个操作码取操作数的地址,它所存储其结果的地址的:

Now suppose we did it without a stack. We'll do it your way, where every opcode takes the addresses of its operands and the address to which it stores its result:

Allocate temporary store T1 for result of A()
Call A() with the address of T1
Allocate temporary store T2 for result of B()
Call B() with the address of T2
Allocate temporary store T3 for the result of the first addition
Add contents of T1 to T2, then store the result into the address of T3
Allocate temporary store T4 for the result of C()
Call C() with the address of T4
Allocate temporary store T5 for result of the second addition
...

您怎么看这个一回事呢?我们的代码是得到的巨大的,因为我们必须明确地分配所有临时存储的通常会按惯例只是去堆栈的。更糟的是,我们的操作码本身都面临巨大的,因为他们现在都必须采取作为一个说法,他们将其结果写入地址,每个操作数的地址。一个添加指令,它知道,它是要采取两件事情从堆栈中,把一件事上可以是一个单字节。 ADD指令,它有两个操作数地址,因此地址将是巨大的。

You see how this goes? Our code is getting huge because we have to explicitly allocate all the temporary storage that would normally by convention just go on the stack. Worse, our opcodes themselves are all getting enormous because they all now have to take as an argument the address that they're going to write their result into, and the address of each operand. An "add" instruction that knows that it is going to take two things off the stack and put one thing on can be a single byte. An add instruction that takes two operand addresses and a result address is going to be enormous.

我们使用基于堆栈的操作码,因为的堆栈解决共同的问题。即:我要分配一些临时存储,很快就用它,然后摆脱它很快,当我完成。 。通过使我们在我们的处置有一个堆栈的假设,我们可以使操作码非常小,代码非常简洁

We use stack-based opcodes because stacks solve the common problem. Namely: I want to allocate some temporary storage, use it very soon and then get rid of it quickly when I'm done. By making the assumption that we have a stack at our disposal we can make the opcodes very small and the code very terse.

更​​新:一些其他的想法。

UPDATE: Some additional thoughts

顺便说一下,这种想法的急剧下降(1)specifing一个虚拟机,(2)编写编译器定位到虚拟机语言,和(3)该VM的写入实现成本上的各种硬件,并不是一个新的想法。它不与MSIL,LLVM,Java字节码,或任何其他现代基础设施发起。最早实施这一战略,我所知道的是1966年从

Incidentally, this idea of drastically lowering costs by (1) specifing a virtual machine, (2) writing compilers that target the VM language, and (3) writing implementations of the VM on a variety of hardware, is not a new idea at all. It did not originate with MSIL, LLVM, Java bytecode, or any other modern infrastructures. The earliest implementation of this strategy I'm aware of is the pcode machine from 1966.

第一,我个人听到这个概念的是当我学会了Infocom的实现者如何设法魔域上这么多不同的机器上运行的这么好。他们指定的虚拟机称为 Z机器然后采用Z机模拟器为所有他们想要的硬件运行其上的游戏。这不得不增加巨大的效益,他们可以实施的虚拟内存管理的本原8位系统;一个游戏可能会大于将融入内存,因为他们可能只是网页从磁盘中的代码时,他们需要它,抛弃它的时候,他们需要加载新的代码。

The first I personally heard of this concept was when I learned how the Infocom implementors managed to get Zork running on so many different machines so well. They specified a virtual machine called the Z-machine and then made Z-machine emulators for all the hardware they wanted to run their games on. This had the added enormous benefit that they could implement virtual memory management on primitive 8-bit systems; a game could be larger than would fit into memory because they could just page the code in from disk when they needed it and discard it when they needed to load new code.

这篇关于什么是堆的目的是什么?我们为什么需要它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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