2008-12-13 51 views
3

我有一個英特爾彙編分配。我需要編寫一個使用2個堆棧的計算器。例如,我有一個像23 + 4/2^4 $這樣的表達式。因此$表示表達式的結尾。我要做的是有兩個堆棧,一個用於數字,一個用於操作員,根據操作員優先級推送和彈出它們。使用2堆棧的計算器

我需要的是如何在同一時間爲兩個不同的目的使用2個堆棧。只要我知道esp寄存器指示堆棧中變量的位置以彈出最後一個或推入一個新的變量。但是如果我只有一個ESP寄存器,我怎麼能有兩個堆棧?

在此先感謝...

回答

4

我認爲你要找的是Dijkstra的調車算法。

只執行所描述的in my blog.

,作爲使額外的堆棧,這是很容易的過程中我已經解決了它沒有解釋期間使用棧。所有的堆棧,實際上只是一個指向頂部和底部的內存區域。每次推動時,都會增加頂部指針,每次彈出時都會減少頂部指針。

0

由於您的兩個堆棧不是獨立的,所以另一個想法是將數據交織在單個堆棧上。例如,您可以對運算符使用偶數編號的字和奇數編號的字。


編輯:在理念闡述的要求,在註釋:我相信每個你推一個操作者的時間,你再要推它後面(因爲反過來,這個數字可能被後面的數更高優先級的運算符)。同樣,每當你彈出操作符時,你將彈出兩個操作數並推送結果。所以操作堆棧和操作數堆棧一起增長和縮小,由於最初的問題是如何在彙編代碼中這樣做,我建議他們可以在單個堆棧上共享交替插槽。 (如果這還不夠詳細,請讓我知道,我會再次編輯。)

+0

我認爲這是一個非常有趣的想法,需要詳細闡述。 – Guge 2008-12-13 22:07:29

+0

交錯堆棧......這個聰明會讓你陷入麻煩 – xxxxxxx 2008-12-14 09:47:43

+0

如果OP將它實現爲RPN,那麼運算符和操作數不會交錯1:1。例如,5 *(6 - 3)將是{6,3, - ,5,*}或甚至{5,6,3, - ,*},我認爲這是分流碼算法會產生的。 – 2008-12-14 19:31:36

2

或者,你可以在最簡單的方式可以工作™並在內存中執行你的執行堆棧;如上所述,您只需要一個TOP指針和一些算術。

-1

所以,我說的對創建兩個棧是這樣的:

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

感謝...

0

想表達的長度爲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。

1

所有這些答案都假定不存在運算符優先級。顯然,在問題中提到的堆棧的使用提示正確的答案與使用操作符優先級的計算有關。

這是一個鏈接,解釋你正在努力實現的目標。 http://epaperpress.com/oper/index.html