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

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

问题描述

所以我学习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 更深入codeS。

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

推荐答案

更​​新:我很喜欢这个问题这么多,我做它的 /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成实机code可以执行。

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#编译器写出机code?

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

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

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.

此外,它是困难和危险的工作。编写高效的code发电机,你是不是一个专家的芯片是一个艰苦的工作!编译器设计师都在自己的语言,而不是对新的芯片集的高效寄存器分配的语义分析的专家。

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 code发电机。此外,语言对CIL发电机是很容易写,因为CIL是一种简单的语言,和CIL到机器code发电机也很容易写,因为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 code为:

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;

假设我们有约定,增加,打电话,店等方面始终走它们的参数从堆栈中,并把他们的结果(如果存在的话)在堆栈中。要生成CIL code这个C#中,我们只说是这样的:

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.

现在假设我们做到了没有一个堆栈。我们会做你的方式,其中的每个运算code利用了它的操作数和地址的地址,它将存储其结果的:

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
...

您怎么看这个去?我们的code越来越的巨大的,因为我们必须明确地分配所有的临时存储的,通常会按约定只是去上堆叠的。更糟的是,我们的运codeS本身都面临巨大的,因为他们现在都必须采取作为一个参数的地址,他们打算写他们的结果为,每一个操作数地址。一个添加指令,它知道,它是要采取两件事情从堆栈中,把一件事上可以是一个单字节。 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.

我们使用基于堆栈的运算codeS,因为栈解决共同的问题的。即:我要分配一些临时存储,使用它很快,然后摆脱它很快,当我完成。通过使我们有一个堆栈我们掌握的假设,我们可以使运算codeS非常小,code非常简洁。

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.

更新:一些更多的想法

顺便说一下,这种想法的大幅度由(1)specifing一个虚拟机,(2)编写编译器为目标的虚拟机语言,并且VM(3)在各种硬件的写入实现降低成本,是不是一个新的主意。它不是起源与MSIL,LLVM,Java字节code,或其他任何现代的基础设施。这个策略我所知道的最早的实现是 p code机从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位系统;一个游戏可能会大于将装入内存,因为他们可能只是页面的code从磁盘当他们需要它,抛弃它的时候,他们需要加载新的code。

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.

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

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