使用 2 个堆栈的计算器

发布于 2024-07-10 11:05:42 字数 255 浏览 8 评论 0原文

我有一项英特尔组装任务。 我需要编写一个使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

安静被遗忘 2024-07-17 11:05:42

我认为您正在寻找的是 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.

说不完的你爱 2024-07-17 11:05:42

或者,您可以采用最简单的方式实现这一点,并在内存中实现两个执行堆栈; 如上所述,您只需要一个 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.

久而酒知 2024-07-17 11:05:42

所有这些答案都假设不存在运算符优先级之类的东西。 显然,问题中提到的堆栈的使用暗示了正确的答案与使用运算符优先级的计算有关。

这是一个解释您想要实现的目标的链接。
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

守不住的情 2024-07-17 11:05:42

由于两个堆栈不是独立的,另一个想法是将数据交错在单个堆栈上。 例如,您可以使用偶数单词表示数字,使用奇数单词表示运算符。


编辑:按照评论中的要求详细阐述这个想法:我相信每次你推送一个运算符时,你都会推送它后面的数字(因为该数字后面可能跟着一个更高优先级的运算符)。 类似地,每次弹出 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.)

习ぎ惯性依靠 2024-07-17 11:05:42

假设表达式的长度为 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.

海螺姑娘 2024-07-17 11:05:42

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

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)? 怎么了?

谢谢...

So, am I right to create two stacks like this:

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:
...

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文