2012-03-21 262 views
7

我在业余时间学习汇编语言以成为更好的开发人员。汇编语言 - 堆栈机

我理解基于堆栈的机器和基于寄存器的机器在概念层面上的区别,但我想知道如何实现基于堆栈的机器。如果虚拟机,例如JVM或.NET,在基于寄存器的架构上运行,例如x86或x64,那么它必须在汇编级别使用寄存器(就我而言)。我显然在这里错过了一些东西。因此我不确定汇编语言的区别。

我已阅读过这里的文章例如Stack-based machine depends on a register-based machine?和维基百科上,但我不相信他们直接回答我的问题。

+0

他们*可以*在软件中模拟它,老的JVM就是这样做的。通常尽管堆栈机器代码被编译为本地代码(无论可能的架构如何)。堆栈机器代码很好,因为它具有简洁的编码,它很容易从AST生成并且相对容易分析。 – harold 2012-03-21 10:24:51

回答

4

那么它必须在组件级别

使用寄存器

这不是一个要求,处理器有一个CPU堆栈,其行为很像中介语言中的虚拟堆栈。您可以将指令几乎一对一地转换为cpu指令。当然,基于堆栈的虚拟机很受欢迎的原因之一是,抖动很容易实现。

这样做的唯一方法就是机器码不是非常高效。抖动优化器的作用是找到有效使用cpu寄存器的方法,并使代码更快。

相反的问题出现在基于寄存器的虚拟机中。由于真正的CPU没有虚拟机的寄存器那么多,所以要解决这个问题是一个难题。所以抖动必须找到方法来使用堆栈溢出硬件不提供的寄存器。

7

基于堆栈的机器很少在硬件上实现 - 我只听说过一个这样的实现,并且从来没有机会在其中工作。

实际上,堆栈机器是由本机解释器在基于真正寄存器的处理器上实现的。实质上,理论堆栈机器由真正的基于寄存器的机器模拟。

所以要回答你的问题:虽然堆栈机器的机器代码没有寄存器,但执行这些指令的本机解释器确实有寄存器并且正在使用它们。

问:那么为什么间接? A:可移植性 - 堆栈机器的指令集可以在任何数量的基于寄存器的不同机器上仿真。这意味着,在同一个JVM的应用程序可以有一个解释,因此,旧的Java口号在任何机器上运行“编写一次,随处运行”

+0

你是什么意思“原生翻译”。你指的是JIT编译器(在.NET的情况下)? – w0051977 2012-03-21 10:04:34

+0

“原生解释器”我的意思是在本地机器上运行的应用程序读取堆栈机器指令后执行它们。每种类型的机器(和操作系统)都会有不同的“本地解释器”。在Java的情况下,“本机解释器”就是JVM。 JIT的情况稍有不同。 – Stormcloud 2012-03-21 10:47:05

+0

仅供参考,JIT是将堆栈机器指令转换为本地机器(基于寄存器的指令)的一组等同指令的东西。这是为了使应用程序的性能接近本机处理器的性能,但同时保持便携性的优势。 – Stormcloud 2012-03-21 12:19:06

6

作为参考,Burroughs B5000Inmos Transputer是堆栈机器。 DEC PDP11有这样灵活的寻址模式,它可以用作堆栈机器。我认为Niklaus Wirth's Lilith可能是一个堆栈机器(超过20年前,我的脑海正在滑倒:-)

他们真的没有任何寄存器名称/编号的指令找到操作数,因为他们在堆栈上。

指令可以将即时(常量)值加载到堆栈上,或加载/存储到内存中。

所以他们是没有add.w r0, r1, r5add.w eax, [#fe34]。有add.w

所以一个例子(不是在所有准确,这是更复杂的)的汇编序列的可能是

loadstack 0xfe34 -- got fe34 onto stack 
loadstackindirect -- use address on the stack, to load the value at that address 
add.w    -- assumes we already have the other operand on the stack 
        -- result back onto the stack 

要计算并加载在数组中的值,可以使用堆栈因为可能有没有索引寻址模式。

因此,指令很小,大量的工作是隐式地使用堆栈和堆栈指针完成的。 IIRC Transputers实际上只有三个值,编译器(或开发人员)必须确保维护。

XMOS现在出售一个现代的“等值”,并雇用一些相同的人。

自从我编写Transputer代码已经有20多年了,所以很抱歉有点含糊。

UCSD Pascal系统使用软件定义的虚拟机,它是一个堆栈机器。这个想法是为了创造一些可以移植到新电脑上的东西,但也易于编写,易于编译和合理的性能。它的虚拟机被定义为它自己的Pascal方言。当它被移植到真正的计算机上时,寄存器将被用来保存堆栈指针,并且可能在处理堆栈顶部(通过寄存器)方面有一些独创性,以获得合理的性能。