Assembly 使用两个堆栈的计算器

Assembly 使用两个堆栈的计算器,assembly,stack,arithmetic-expressions,Assembly,Stack,Arithmetic Expressions,我有英特尔汇编作业。我需要写一个使用两个堆栈的计算器。例如,我有一个类似23+4/2^4$的表达式,因此$表示表达式的结尾。我要做的是有两个堆栈,一个用于数字,一个用于运算符,并根据运算符优先级推送和弹出它们 我需要的是如何在同一时间为两个不同的目的使用两个堆栈。只要我知道,esp寄存器指示堆栈中变量的位置,以弹出最后一个或推送新的变量。但是如果我只有一个esp寄存器,我怎么能有两个堆栈呢 先谢谢你 我想你要找的是Dijkstra的分流算法 我在解释过程中没有使用堆栈就解决了这个问题,只是在执行

我有英特尔汇编作业。我需要写一个使用两个堆栈的计算器。例如,我有一个类似23+4/2^4$的表达式,因此$表示表达式的结尾。我要做的是有两个堆栈,一个用于数字,一个用于运算符,并根据运算符优先级推送和弹出它们

我需要的是如何在同一时间为两个不同的目的使用两个堆栈。只要我知道,esp寄存器指示堆栈中变量的位置,以弹出最后一个或推送新的变量。但是如果我只有一个esp寄存器,我怎么能有两个堆栈呢


先谢谢你

我想你要找的是Dijkstra的分流算法

我在解释过程中没有使用堆栈就解决了这个问题,只是在执行过程中如前所述


至于制作额外的堆栈,这是相当容易的。所有堆栈实际上只是一个内存区域,带有指向顶部和底部的指针。每次按下时,都会增加顶部指针,每次弹出时,都会减少顶部指针。

由于两个堆栈不是独立的,另一种方法是在单个堆栈上交错数据。例如,可以对数字使用偶数字,对运算符使用奇数字



编辑:按照评论中的要求详细阐述这个想法:我相信每次你推一个操作符,你就会推它后面的数字(因为这个数字后面可能会有一个优先级更高的操作符)。类似地,每次弹出and运算符时,都会弹出两个操作数并推送一个结果。因此,运算符堆栈和操作数堆栈是连续增长和收缩的,因为最初的问题是如何在汇编代码中实现这一点,我建议它们可以在单个堆栈上共享交替插槽。(如果这还不够详细,请让我知道,我会再次编辑。)

或者,您可以用最简单的方式完成™ 并在内存中实现两个执行堆栈;如上所述,您只需要一个顶部指针和一些算术运算。

那么,我创建两个这样的堆栈是否正确:

mov ecx,256
L1: call ReadInt
    push eax          ;push the integer to where esp=1 points
    add esp,ecx       ;esp=1+256=257, now esp points to 257.

    call ReadChar     ;read operand
    cmp al,endChar    ;compare with end sign=$
    je next       
    push al           ;push operand to where esp=257 points
    sub esp,ecx       ;esp=257-256=1, now esp is in the original position
    loop L1
next:
...
当然,注释是针对第一个循环的

顺便说一句,我得到了一个“1>。\main.asm(46):错误A2149:字节寄存器不能作为第一个操作数”(push al)错误?怎么了


谢谢…

假设表达式的长度为L,则每个堆栈最多为L,因此您最多需要2L内存。
将ESP增加2L,在ESP时,您将拥有第一个堆栈的Begining,在ESP+L时,您将拥有第二个堆栈的Begining(需要注意的是,这些堆栈都不会超过L,因为表达式的长度为L)。
调车场算法可以在不同的地方找到。它所做的是从中缀符号转换而来
后缀表示法。在那之后,后缀符号的评估就不难了

编辑:另外,要操作这两个堆栈,您需要将它们的堆栈指针存储在某个位置。
您可以使用您选择的两个寄存器,例如EBX、ECX
使其中一个值为ESP,另一个值为ESP+L。
每次使用一个或另一个堆栈时,您都必须使用适当的EBX或ECX更新ESP,或者在您可能保留两个堆栈指针的任何位置更新ESP,因为push和pop将修改ESP,您希望他们修改所需的ESP版本,而不是另一个版本。此外,当您完成pop/push时,您必须使用值更新EBX/ECX尤其是,所有这些答案都假定不存在运算符优先级。显然,问题中提到的堆栈的使用暗示了正确答案与使用运算符优先级的计算有关

这里有一个链接,解释了你想要实现的目标。

我认为这是一个非常有趣的想法,需要详细阐述。交错堆栈。。。这种聪明会让你陷入麻烦。如果OP将其实现为RPN,那么运算符和操作数将不会以1:1的比例交错。例如,5*(6-3)将是{6,3,-,5,}或甚至{5,6,3,-,},我认为这是调车场算法将生成的结果。“所有这些答案都假设不存在操作员优先权”?什么?你从哪里得到这个结论的?这个问题是著名的运算符优先问题,由著名的中缀符号解决。上面的答案似乎没有考虑到堆栈,并且谈论移除堆栈,这会破坏上述练习的目的。我想你不知道你在说什么。如果在“添加esp,ecx”和“子esp,ecx”之间发生中断,你会遇到麻烦。相反,您必须维护两个指向堆栈的指针。一个可以是esp,另一个应该是ebp。至于您的错误(“字节寄存器不能是第一个操作数”),您必须按eax,而不是al。您只能按全宽寄存器。esp应始终在机器字边界上对齐。