gpt4 book ai didi

assembly - 在过程中操作运行时堆栈

转载 作者:行者123 更新时间:2023-12-01 13:15:49 27 4
gpt4 key购买 nike

我正在开发一个包含两个过程的程序。一种将 N 个无符号双字数组压入堆栈,另一种从堆栈弹出 N 个无符号双字并将它们存储在数组中。我能够成功地将所有元素压入堆栈,但是由于堆栈指针(esp 寄存器)已更改,因此过程无法返回到主程序。

我已经能够通过操作 esp 寄存器返回到 main 以便保存返回地址,然后我将该地址重新加载到 esp 在我返回之前。但是,在调用下一个过程时,我压入堆栈的条目已被覆盖。

在过程中工作时是否有正确的方法将数据保存在堆栈中?

这是我的一些代码:

主要过程:

main PROC
main_loop:
; Main menu
mov edx, offset choicePrompt
call WriteString

read_input:
call ReadInt
jno good_input
jmp main_loop

good_input:
cmp eax, 0
je create_vector
cmp eax, 1
je array_stack
cmp eax, 2
je stack_array
cmp eax, -1
je end_program

call crlf
jmp main_loop

create_vector:
call CreateVector
jmp end_options

array_stack:
call ArrayToStack
jmp end_options

stack_array:
call StackToArray
jmp end_options

end_options:
call crlf
jmp main_loop

end_program:
mov edx, offset exitPrompt
call WriteString
call crlf
exit
main ENDP

ArrayToStack 过程中将数组压入堆栈:

mov esi, offset Vector
mov ebx, N
dec ebx
mov eax, 0
mov ecx, -1

push_array_loop:
inc ecx
mov al, [esi + ecx]
push eax
mov [esi + ecx], byte ptr(0)
cmp ecx, ebx
jl push_array_loop

StackToArray 过程中将堆栈写入控制台:

mov eax, N
mov ebx, 4
mul ebx
mov ebx, eax
mov ecx, 0
write_stack_loop:
mov eax, [esp + ecx]
add ecx, 4
call WriteDec
mov edx, offset spacePrompt
call WriteString
cmp ecx, ebx
jl write_stack_loop

最佳答案

检查你的场所。在您的第一段中,您谈到了一个将 N 个无符号双字数组推送到堆栈的过程,但您的代码处理的是一个 N 个无符号字节数组。

此外,我观察到您在控制台上的输出将以相反的顺序(到数组)并且您的代码在读取输入数组时将其归零。我已将所有这些内容保存在以下解决方案中。

前 2 个片段将保留 ECXEDX。他们破坏 EAX

对您的编码问题的真正解释当然是查看堆栈在每一步中是如何被修改的。仔细观察!

ArrayToStack:

[ ret ]
^ esp

mov eax, N ; The number of array elements is a runtime value
dec eax
shl eax, 2
sub esp, eax

<-- eax = (N-1)*4 -->
[ ][ ... ][ ][ ret ]
^ esp

push dword ptr [esp + eax]

[ ret ][ ][ ... ][ ][ ]
^ esp

push ecx
push edx

[ edx ][ ecx ][ ret ][ ][ ... ][ ][ ]
^ esp

xor ecx, ecx
ToStack:
xor edx, edx
xchg dl, [Vector + ecx] ; Reading byte-sized element while zeroing the source
mov [esp + 12 + eax], edx
inc ecx
sub eax, 4
jnb ToStack

[ edx ][ ecx ][ ret ][ a_N ][ ... ][ a_2 ][ a_1 ]
^ esp ^ esp+12

pop edx
pop ecx

[ ret ][ a_N ][ ... ][ a_2 ][ a_1 ]
^ esp

ret ; EAX ends at -4

[ a_N ][ ... ][ a_2 ][ a_1 ]
^ esp


StackToConsoleProcedure:

[ ret ][ a_N ][ ... ][ a_2 ][ a_1 ]
^ esp

push ecx
push edx

[ edx ][ ecx ][ ret ][ a_N ][ ... ][ a_2 ][ a_1 ]
^ esp ^ esp+12

xor ecx, ecx
FromStack:
mov eax, [esp + 12 + ecx*4]
call WriteDec
mov edx, offset spacePrompt
call WriteString
inc ecx
cmp ecx, N
jb FromStack
shl ecx, 2 ; ECX = N*4
mov eax, [esp + 8] ; Fetch return address
mov [esp + 8 + ecx], eax

<-------- ecx = N*4 ------->
[ edx ][ ecx ][ ][ a_N ][ ... ][ a_2 ][ ret ]
^ esp ^ esp+8

mov eax, ecx
pop edx
pop ecx

<-------- eax = N*4 ------->
[ ][ a_N ][ ... ][ a_2 ][ ret ]
^ esp

add esp, eax

[ ret ]
^ esp


ret ; EAX ends at N*4

如果不需要保留 ECXEDX 寄存器,但仍然允许 EAX 被破坏:

ArrayToStack:
mov eax, N
dec eax
shl eax, 2
sub esp, eax
push dword ptr [esp + eax]
xor ecx, ecx
ToStack:
xor edx, edx
xchg dl, [Vector + ecx]
mov [esp + 4 + eax], edx
inc ecx
sub eax, 4
jnb ToStack
ret

StackToConsoleProcedure:
xor ecx, ecx
Fromtack:
mov eax, [esp + 4 + ecx*4]
call WriteDec
mov edx, offset spacePrompt
call WriteString
inc ecx
cmp ecx, N
jb FromStack
shl ecx, 2
pop eax
add esp, ecx
push eax
ret

关于assembly - 在过程中操作运行时堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55171120/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com