使用 2 个堆栈的计算器
我有一项英特尔组装任务。 我需要编写一个使用 2 个堆栈的计算器。 例如,我有一个像 23+4/2^4$ 这样的表达式。因此 $ 表示表达式的结尾。 我要做的是有两个堆栈,一个用于数字,一个用于运算符,并根据运算符优先级压入和弹出它们。
我需要的是如何同时使用2个堆栈用于两个不同的目的。 据我所知 esp 寄存器指示堆栈中变量弹出最后一个变量或推送新变量的位置。 但如果我只有一个 esp 寄存器,怎么会有两个堆栈呢?
提前致谢...
I have an intel assembly assignment. I need to write a calculator which uses 2 stacks. For example, i have an expression like 23+4/2^4$ .So that $ indicates the end of expression. What I will do is to have two stacks, one for numbers, one for operators and push and pop them according to the operator precedence.
What I need is how can I use 2 stacks for two different purpose at the same time. As long as I know esp register indicates the place for variables in the stack to pop the last or to push a new one. But if I only have one esp register, how can I have two stacks?
Thanks in advance...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我认为您正在寻找的是 Dijkstra 的分流算法。
我已经解决了这个问题,在解释期间没有使用堆栈,仅在执行期间如我的博客中所述所述。
至于制作额外的堆栈,这很容易。 堆栈实际上只是一个带有指向顶部和底部的指针的内存区域。 每次压入时,都会增加顶部指针,每次弹出时都会减少顶部指针。
I think what you're looking for is Dijkstra's shunting algorithm.
I have solved it without using stacks during interpretation, only during execution as described in my blog.
As for making extra stacks, it is quite easy. All a stack is, is really just an area of memory with a pointer to the top and bottom. Every time you push, you increment the top pointer, every time you pop you decrement the top pointer.
或者,您可以采用最简单的方式实现这一点,并在内存中实现两个执行堆栈; 如上所述,您只需要一个 TOP 指针和一些算术。
Or, you could do it in the Simplest Way That Could Possibly Work™ and implement both your execution stacks in memory; as above, you only need a TOP pointer and some arithmetic.
所有这些答案都假设不存在运算符优先级之类的东西。 显然,问题中提到的堆栈的使用暗示了正确的答案与使用运算符优先级的计算有关。
这是一个解释您想要实现的目标的链接。
http://epaperpress.com/oper/index.html
All these answers assume that there is no such thing as operator precedence. Clearly the use of stacks mentioned in the question hints at the correct answer having to do with the calculation making use of operator precedence.
Here is a link that explains what you are trying to achieve.
http://epaperpress.com/oper/index.html
由于两个堆栈不是独立的,另一个想法是将数据交错在单个堆栈上。 例如,您可以使用偶数单词表示数字,使用奇数单词表示运算符。
编辑:按照评论中的要求详细阐述这个想法:我相信每次你推送一个运算符时,你都会推送它后面的数字(因为该数字后面可能跟着一个更高优先级的运算符)。 类似地,每次弹出 and 运算符时,您都会弹出两个操作数并推送一个结果。 因此,运算符堆栈和操作数堆栈同时增长和收缩,并且由于最初的问题是如何在汇编代码中执行此操作,因此我建议它们可以在单个堆栈上共享交替的插槽。 (如果这还不够详细,请告诉我,我会再次编辑。)
Since your two stacks are not independent, another idea would be to interleave the data on a single stack. For example, you could use even-numbered words for numbers and odd-numbered words for operators.
Edit: elaborating on the idea as requested in comment: I believe that every time you push an operator, you are then going to push the number that follows it (because that number in turn might be followed by an operator of higher precedence). Similarly, every time you pop and operator, you are going to pop two operands and push a result. So the operator stack and the operand stack grow and shrink in tandem, and since the original question was how to do this in assembly code, I suggested they could share alternating slots on a single stack. (If that's not sufficient elaboration, please let me know and I will edit again.)
假设表达式的长度为 L ,那么每个堆栈最多为 L ,因此最多需要 2L 内存。
将 ESP 增加 2L ,在 ESP 处,您将获得第一个堆栈的开始,在 ESP+L 处,您将获得第二个堆栈的开始(应该注意的是,这些堆栈都不会超过 L,因为表达式的长度L)。
调车场算法在很多地方都可以找到。它所做的就是中缀表示法的转换
后缀表示法。 之后后缀表示法的评估就不难了。
编辑:另外,为了操作 2 个堆栈,您需要将它们的堆栈指针存储在某处。
您可以使用您选择的 2 个寄存器,例如 EBX、ECX
使一个具有值 ESP,另一个具有值 ESP+L。
每次您使用一个堆栈或另一个堆栈时,您都必须使用适当的 EBX 或 ECX 或任何您可以保留 2 个堆栈指针的位置来更新 ESP,因为压入和弹出将修改 ESP,并且您将希望它们修改需要的 ESP 版本。是必需的,而不是另一个。此外,当您完成弹出/推送时,您必须使用 ESP 的值更新 EBX/ECX。
suppose the expression has length L , then each of your stacks will be at most L, so you will need at the most 2L memory.
increase ESP by 2L , at ESP you will have the beggining of your first stack,at ESP+L you will have the beggining of your second stack(it should be noted that neither of these stacks will ever exceed L beacause the expression is of length L).
The shunting yard algorithm can be found in various places.What it does is the conversion from infix notation
to postfix notation. After that the evaluation of the postfix notation will not be hard.
Edit: also,for manipulating the 2 stacks,you will need to store their stack pointers somewhere .
You can use 2 registers of your choice for that, EBX,ECX for example
make one have the value ESP and the other ESP+L.
Every time you will use one stack or the other you will have to update ESP with the appropriate EBX or ECX or wherever you may keep your 2 stack pointers because push and pop will modify ESP and you will want them to modify the version of ESP that is needed and not another one.Also when you finished pop/push you must update EBX/ECX with the values of ESP.
那么,我创建两个这样的堆栈是否正确:
当然,注释是针对第一个循环的。
顺便说一句,我收到“1>..\main.asm(46):错误 A2149:字节寄存器不能是第一个操作数”错误(push al)? 怎么了?
谢谢...
So, am I right to create two stacks like this:
Of course the comments are for the first loop.
BTW, I got an "1>..\main.asm(46) : error A2149:byte register cannot be first operand" error for (push al)? what's the matter?
thanks...