2015-04-13 66 views
1

我是新裝配。我已經做了幾個月。當我嘗試將值推送到我自己的堆棧數組時,我收到一個錯誤,該程序崩潰了我的程序。錯誤說「訪問衝突寫入位置」。我用調試器完成了它,並沒有發現任何東西。所以,我在程序的開始處放置了產生錯誤的代碼,以查看是否有其他代碼(僅從目前的文件讀取)可能導致該錯誤。我仍然得到錯誤。請幫助我,我不知道發生了什麼事。這裏是我的代碼:錯誤推送到我自己的堆棧中裝配Masm x86

.data 
myStack DWORD 30 DUP(?) 
top DWORD $ 
val DWORD 5 

.code 
mov esi, OFFSET myStack 
mov eax, val 
add esi, top 
sub esi, 4    
mov [esi], eax ;this is where it crashes 

回答

1

除非有一個重要的原因,爲什麼你的籌碼必須工作,比如處理器的堆棧(即「頂」向下增長),它更容易與「頂」要做到這一點朝分配的緩衝區結束。原因是你不必回頭想辦法做到這一點。堆棧就像任何其他緩衝區一樣。您將第一個項目添加到第一個位置,並朝分配的緩衝區的末尾增長。

「推」是一個項目添加到下一個可用的位置的問題。 「流行」是從最高使用位置移除的問題。

請注意,效率與我的論點無關。無論哪種方式,你都會做同樣的工作。思考起來更容易一些,因爲堆棧像其他任何數組類型結構一樣實現:您添加的第一個項目會轉到第一個(編號最小的)地址等等。它只是您以LIFO順序訪問的緩衝區。

如果要實現它,我建議:

.data 
myStack DWORD 30 DUP(?) 
top DWORD myStack 
val DWORD 5 

.code 

MyPush: 
    // call with EAX containing the value you want to store 
    mov esi,[top] 
    mov [esi],eax 
    add esi,4 
    mov [top],esi 
    ret 

MyPop: 
    // returns the value on the top of the stack in EAX 
    mov esi,[top] 
    sub esi,4 
    mov eax,[esi] 
    mov [top],esi 
    ret 
+0

我認爲如果我這樣做,我的教授就會倒數。那麼它不會是一個傳統的堆棧。儘管如此,我現在一切正常。只需要幾個錯誤來應對。謝謝,@Jim Mischel! – lisabits

+0

我覺得絆倒我的是,我從來沒有訪問過一個數組,但沒有加載它。我的意思是,我知道它正在記憶中的其他地方,但最初無法弄清楚原因。現在一切都說得通了。 – lisabits

+0

@lisabits:不要混淆你的堆棧的*實現*和*接口*。堆棧是可以添加項目的抽象數據類型。當你刪除一個項目,你總是得到最近添加的項目。你如何實現它並不重要。項目的收集是否在你的緩衝區中「向上」或「向下」增長,或者你以某種方式隨機存儲它們是無關緊要的。重要的是,它以正確的順序返回項目。見http://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29 –

0

假設它的增長下來,典型的基於微處理器的堆棧,然後把東西到堆棧中:

  1. 遞減堆棧指針
  2. 移動值到什麼堆棧指針指向

並取下堆棧中的東西:

  1. 檢索堆棧指針指向
  2. 遞增堆棧指針

當你總結topmyStack,你會得到什麼這是遙遠的其他地方的地址,可能是外面的你程序空間。 top本身已經是堆棧頂部的地址,而無需添加任何內容。

所以在你的情況下,top已經是堆棧的頂部。所以,你的初始堆棧指針應top

.data 
myStack DWORD 30 DUP(?) 
top DWORD $ 
val DWORD 5 

.code 
mov esi, OFFSET top ; Initialize the stack pointer 
mov eax, val   ; Load a value into eax 
sub esi, 4    ; push eax onto the stack 
mov [esi], eax 

在上文中,4從「堆棧指針」(這是最初top)所述第一減法將產生top - 4也就是最後4個字節的空間,在你myStack地區。

彈出一個值從堆棧中:

mov eax, [esi] 
add esi, 4 

或者,你也能設置不同top,然後你的代碼會工作。但它是稍微複雜:

.data 
myStack DWORD 30 DUP(?) 
top DWORD $-myStack   ; the value here is current location minus myStack 
val DWORD 5 

.code 
mov esi, OFFSET myStack  ; Setup the stack pointer 
add esi, top 
mov eax, val     ; get value in eax 
sub esi, 4      ; push eax   
mov [esi], eax 
+0

AHHHH!好的,非常感謝你,@lurker!這是我第一次使用$,所以我很困惑。所以我不需要加載myStack? – lisabits

+0

@lisabits'$'只是表示當前的程序計數器。所以'top'指向它自己地址的副本。在這種情況下,由於您使用標籤來表示堆棧末尾的位置,因此「top」指向哪個值並不重要。 – lurker

+0

@lisabits,如果你有'頂級DWORD $ -myStack'而不是'頂級DWORD $',你的代碼就可以工作。 – lurker