在 Assembly Masm x86 中推送到我自己的堆栈时出错
Error Pushing To My Own Stack in Assembly Masm x86
我是装配新手。我已经做了几个月了。当我尝试将一个值压入我自己的堆栈数组时,我遇到了一个使我的程序崩溃的错误。错误显示,"Access Violation Writing Location"。我已经用调试器逐步检查它,但一无所获。因此,我将生成错误的代码放在程序的开头,以查看是否有其他代码(目前只是从文件中读取)可能导致了错误。我仍然得到错误。请帮助我,我不知道发生了什么。这是我的代码:
.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
假设它增长向下,典型的基于微处理器的堆栈,然后将一些东西放到堆栈上:
- 递减堆栈指针
- 将值移动到栈指针指向的地方
然后从堆栈中取出一些东西:
- 检索堆栈指针指向的内容
- 增加堆栈指针
当您将 top
加到 myStack
时,您将得到一个与其他地方相去甚远的地址,可能在您的程序 space 之外。 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
在上面,"stack pointer"(最初是 top
)第一次减去 4 将得到 top - 4
,这是最后 4 个字节 space在你的 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
除非有一个压倒一切的原因为什么你的堆栈 必须 像处理器的堆栈一样工作(即 "top" 向下增长),使用 "top" 到分配缓冲区的末尾。原因是您不必向后思考即可。堆栈变得就像任何其他缓冲区一样。您在第一个位置添加第一个项目,并向分配缓冲区的末尾增长。
"Push"是往下一个可用位置添加一个item的事情。 "Pop"是从最高使用位置移除的问题。
请注意,效率与我的论点无关。无论哪种方式,您所做的工作量都是相同的。这只是更容易考虑,因为堆栈的实现方式与任何其他数组类型结构一样:您添加的第一项将进入第一个(编号最小的)地址,等等。它只是一个缓冲区,您可以按 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
我是装配新手。我已经做了几个月了。当我尝试将一个值压入我自己的堆栈数组时,我遇到了一个使我的程序崩溃的错误。错误显示,"Access Violation Writing Location"。我已经用调试器逐步检查它,但一无所获。因此,我将生成错误的代码放在程序的开头,以查看是否有其他代码(目前只是从文件中读取)可能导致了错误。我仍然得到错误。请帮助我,我不知道发生了什么。这是我的代码:
.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
假设它增长向下,典型的基于微处理器的堆栈,然后将一些东西放到堆栈上:
- 递减堆栈指针
- 将值移动到栈指针指向的地方
然后从堆栈中取出一些东西:
- 检索堆栈指针指向的内容
- 增加堆栈指针
当您将 top
加到 myStack
时,您将得到一个与其他地方相去甚远的地址,可能在您的程序 space 之外。 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
在上面,"stack pointer"(最初是 top
)第一次减去 4 将得到 top - 4
,这是最后 4 个字节 space在你的 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
除非有一个压倒一切的原因为什么你的堆栈 必须 像处理器的堆栈一样工作(即 "top" 向下增长),使用 "top" 到分配缓冲区的末尾。原因是您不必向后思考即可。堆栈变得就像任何其他缓冲区一样。您在第一个位置添加第一个项目,并向分配缓冲区的末尾增长。
"Push"是往下一个可用位置添加一个item的事情。 "Pop"是从最高使用位置移除的问题。
请注意,效率与我的论点无关。无论哪种方式,您所做的工作量都是相同的。这只是更容易考虑,因为堆栈的实现方式与任何其他数组类型结构一样:您添加的第一项将进入第一个(编号最小的)地址,等等。它只是一个缓冲区,您可以按 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