我在业余时间学习汇编语言,成为一名更好的开发人员.
我理解基于堆栈的机器和基于寄存器的机器在概念层面上的区别,但我想知道基于堆栈的机器是如何实际实现的.如果虚拟机(例如JVM或.NET)在基于寄存器的体系结构(例如x86或x64)上运行,那么它必须在汇编级别使用寄存器(就我而言).我显然在这里遗漏了一些东西.因此,我不确定汇编语言的区别.
我在这里阅读过文章,例如基于堆栈的机器依赖于基于寄存器的机器?以及维基百科,但我不相信他们会直接回答我的问题.
基于堆栈的机器很少在硬件中实现 - 我只听说过一个这样的实现,并且从未有机会在一个机器上工作.
实际上,堆栈计算机由本机解释器在基于真实寄存器的处理器上实现.从本质上讲,理论Stack机器是由真正的基于寄存器的机器模拟的.
所以回答你的问题:虽然堆栈机器的机器代码没有寄存器,但执行这些指令的本机解释器确实有寄存器并将使用它们.
问:为什么间接?答:可移植性 - 可以在任意数量的不同基于寄存器的机器上模拟堆栈机器的指令集.这意味着可以在任何具有解释器的计算机上运行相同的JVM应用程序,因此旧的Java口号"一次编写,随处运行"
作为参考,Burroughs B5000和Inmos Transputer是堆叠机器.DEC PDP11具有这种灵活的寻址模式,可以用作堆栈机器.我认为Niklaus Wirth的Lilith可能是一台堆叠机器(20多年前,我的脑子在滑倒:-)
他们在查找操作数的指令中确实没有任何寄存器名称/编号,因为它们在堆栈中.
指令可以将立即(常量)值加载到堆栈中,或加载/存储到内存中.
所以他们没有add.w r0, r1, r5
或add.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
Run Code Online (Sandbox Code Playgroud)
要计算并加载数组中的值,可能会使用堆栈,因为可能没有索引寻址模式.
因此指令很小,并且使用堆栈和堆栈指针隐式完成了大量工作.IIRC Transputers实际上只有三个值的堆栈,编译器(或开发人员)必须确保维护.
XMOS现在销售一种现代的"等价物",雇用一些同样的人.
自从我编写Transputer代码已有20多年了,很抱歉有点模糊.
的UCSD帕斯卡系统中使用的定义的虚拟机软件,这是一个堆栈的机器.我们的想法是制作可移植到新计算机上的东西,但也易于编写,易于编译和合理的性能.它的虚拟机是用自己的Pascal方言定义的.当它被移植到真实计算机时,寄存器将用于保存堆栈指针,并且可能在堆栈顶部如何处理(通过寄存器)方面具有一些独创性,以便获得合理的性能.
那么它必须在汇编级别使用寄存器
这不是必需的,处理器有一个 cpu 堆栈,其行为很像中间语言中的虚拟堆栈。您可以将指令几乎一对一地转换为 cpu 指令。当然,基于堆栈的虚拟机流行的原因之一是抖动很容易实现。
这样做的唯一问题是机器代码效率不高。抖动优化器的工作就是找到有效使用 cpu 寄存器的方法并使代码更快。
基于寄存器的虚拟机中存在相反的问题。这是一个更难解决的问题,因为真实的 CPU 没有虚拟机那么多的寄存器。因此抖动必须找到使用堆栈来溢出硬件不提供的寄存器的方法。
归档时间: |
|
查看次数: |
1443 次 |
最近记录: |