汇编语言 - 堆栈机器

时间:2012-03-21 09:22:01

标签: assembly x86 masm

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

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

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

3 个答案:

答案 0 :(得分:7)

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

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

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

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

答案 1 :(得分: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方言定义的。当它被移植到真实计算机时,寄存器将用于保存堆栈指针,并且可能在堆栈顶部如何处理(通过寄存器)方面具有一些独创性,以便获得合理的性能。

答案 2 :(得分:4)

  

然后它必须在汇编级别使用寄存器

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

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

基于寄存器的VM存在相反的问题。这是一个难以解决的问题,因为真正的CPU没有与VM一样多的寄存器。因此,抖动必须找到使用堆栈溢出硬件未提供的寄存器的方法。