2015-04-13 40 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