Assembly 在过程中操作运行时堆栈
我正在编写一个包含两个过程的程序。一种是将N个无符号双字数组推送到堆栈中,另一种是从堆栈中弹出N个无符号双字并将其存储在数组中。我能够成功地将所有元素推送到堆栈,但由于堆栈指针(Assembly 在过程中操作运行时堆栈,assembly,x86,masm,irvine32,irvine16,Assembly,X86,Masm,Irvine32,Irvine16,我正在编写一个包含两个过程的程序。一种是将N个无符号双字数组推送到堆栈中,另一种是从堆栈中弹出N个无符号双字并将其存储在数组中。我能够成功地将所有元素推送到堆栈,但由于堆栈指针(espregister)已更改,因此该过程无法返回到主程序 我已经能够通过操纵esp寄存器返回main,以便保存返回地址,并在返回之前将该地址重新加载到esp。但是,在调用下一个过程时,我推送到堆栈中的条目已被覆盖 在过程中工作时,是否有正确的方法将数据保存在堆栈中 以下是我的一些代码: 主要程序: main PROC
esp
register)已更改,因此该过程无法返回到主程序
我已经能够通过操纵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
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
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
在ArrayToStack过程中将阵列推送到堆栈:
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
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
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
在StackToArray过程中将堆栈写入控制台:
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
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
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
当过程p需要存储的数据的生存期超过了p的生存期时,数据不能存储在p的堆栈帧内的堆栈上,因为正如您所发现的,当p返回时,数据会“消失” 这里有几个其他的选择会起作用
检查你的房子。在第一段中,您讨论了将N个无符号双字数组推入堆栈的过程,但您的代码处理的是N个无符号字节数组 此外,我注意到控制台上的输出顺序与arrray相反,并且代码在读取输入数组时将其归零。我把所有这些都保存在下面的解决方案中 前两个代码段将保留
ECX
和EDX
。它们确实会重击EAX
对编码问题的真正解释当然是看看堆栈是如何随着每个步骤而修改的。仔细看
选项3:通过将返回地址复制到数组下方,使ESP保持修改状态的自定义调用约定。(例如,
pop ecx
输入以获取返回地址。将数据像std::vector一样推送到堆栈上,或者在堆栈上创建一个数组。使用push ecx
/ret
返回)调用函数的堆栈框架将增长,以包括这个新数组。@Peter,是的,我考虑过建议这样做(仅供专家使用)但是决定反对,因为这个答案不是针对专家的。