3

インテルアセンブリの割り当てがあります。2つのスタックを使用する計算機を作成する必要があります。たとえば、23 + 4/2 ^ 4 $のような式があります。したがって、$は式の終わりを示します。私が行うことは、2つのスタック(1つは数値用、もう1つは演算子用)を用意し、演算子の優先順位に従ってそれらをプッシュおよびポップすることです。

必要なのは、2つのスタックを2つの異なる目的に同時に使用するにはどうすればよいかということです。私が知っている限り、esp registerは、スタック内の変数が最後をポップする場所、または新しい変数をプッシュする場所を示します。しかし、espレジスタが1つしかない場合、どうすれば2つのスタックを持つことができますか?

前もって感謝します...

4

6 に答える 6

4

あなたが探しているのは、ダイクストラのシャントアルゴリズムだと思います。

私は、ブログで説明されているように、実行中にのみ、解釈中にスタックを使用せずに問題を解決しました。

余分なスタックを作ることに関しては、それは非常に簡単です。すべてのスタックは、実際には、上下へのポインタを持つ単なるメモリ領域です。押すたびにトップポインタをインクリメントし、ポップするたびにトップポインタをデクリメントします。

于 2008-12-13T21:37:35.437 に答える
2

または、可能な限り機能する最も単純な方法で実行し、両方の実行スタックをメモリに実装することもできます。上記のように、TOP ポインターといくつかの演算のみが必要です。

于 2008-12-13T22:19:43.073 に答える
1

これらのすべての回答は、演算子の優先順位などがないことを前提としています。明らかに、質問で言及されているスタックの使用は、演算子の優先順位を利用する計算に関係する正しい答えを示唆しています。

これは、あなたが達成しようとしていることを説明するリンクです。 http://epaperpress.com/oper/index.html

于 2008-12-13T23:28:43.853 に答える
0

式の長さが L であると仮定すると、各スタックは最大で L になるため、最大で 2L のメモリが必要になります。
ESP を 2L 増やします。ESP では最初のスタックが開始され、ESP+L では 2 番目のスタックが開始されます (式が長いため、これらのスタックのどちらも L を超えることはないことに注意してください)。 L)。
操車場アルゴリズムはさまざまな場所で見つけることができます。それが行うのは、中置表記から後置表記への変換
です。その後、後置表記の評価は難しくありません。

編集: また、2 つのスタックを操作するには、スタック ポインターをどこかに保存する必要があります。
そのために、任意の 2 つのレジスタを使用できます。たとえば、EBX、ECX を使用すると、
1 つの値が ESP になり、もう 1 つのレジスタが ESP+L になります。いずれかのスタックを使用するたびに、適切な EBX または ECX を使用して ESP を更新する必要があります。または、プッシュとポップによって ESP が変更され、ESP のバージョンを変更する必要があるため、2 つのスタック ポインターを保持できる場所であればどこでも更新する必要があります。が必要であり、別のものではありません。また、ポップ/プッシュを終了したら、ESP の値で EBX/ECX を更新する必要があります。

于 2008-12-13T23:10:39.523 に答える
0

2 つのスタックは独立していないため、1 つのスタックでデータをインターリーブするという別のアイデアがあります。たとえば、数字には偶数番号の単語を使用し、演算子には奇数番号の単語を使用できます。


編集:コメントで要求されたアイデアを詳しく説明します:演算子をプッシュするたびに、それに続く番号をプッシュすると思います(その番号の後に、優先順位の高い演算子が続く可能性があるため)。同様に、ポップ アンド オペレータを実行するたびに、2 つのオペランドをポップして結果をプッシュします。したがって、演算子スタックとオペランド スタックは連動して拡大縮小します。元の質問はアセンブリ コードでこれを行う方法だったので、1 つのスタックで交互のスロットを共有することを提案しました。(これで十分でない場合はお知らせください。再度編集します。)

于 2008-12-13T22:00:29.023 に答える
-1

では、次のような 2 つのスタックを作成するのは正しいでしょうか。

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) で発生しましたか? どうしたの?

ありがとう...

于 2008-12-13T22:47:27.307 に答える