你好,我想在内存中保存一个由用户定义的长度和值的数组。实际上我是在存储插入在“[ebp+8+esi*4]"的值,所以在函数参数之后。这是正确的吗?或者我应该怎么做?我认为局部变量应该放在esp下面的内存地址,所以通过递减esp为局部变量腾出空间。但是我不能动态递减“esp”,那我该怎么办呢?
这是代码:
.686
.xmm
.model flat, C
OPTION CaseMap:None
include ../masm32/libs/windows.inc
include ../masm32/libs/kernel32.inc
include ../masm32/libs/user32.inc
include ../masm32/libs/msvcrt.inc
include ../masm32/libs/masm32.inc
EXTERN printf:PROC
EXTERN scanf:PROC
.data
str_insert_array_length db "Insert Array Length: ",0
str_insert_value db 10,"Insert Value: ",0
str_input_format db "%d",0
str_format_print db "%d",10,0
input_length DWORD 0
input_value DWORD 0
.code
main PROC
push ebp
mov ebp,esp
push offset str_insert_array_length
call printf
add esp,4
push offset input_length
push offset str_input_format
call scanf
add esp,8
mov edi,[input_length]
array_input:
push offset str_insert_value
call printf
add esp,4
push offset input_value
push offset str_format
call scanf
add esp,8
mov eax, [input_value]
push eax
dec edi
jnz array_input
mov edi,[input_length]
xor esi,esi
push offset str_print_array
call printf
add esp,4
print_array:
mov edx,[esp+4*esi]
push edx
push offset str_format_print
call printf
add esp,8
inc esi
dec edi
jnz print_array
pop ebp
invoke ExitProcess,0
main ENDP
end
1条答案
按热度按时间woobm2wo1#
您可以动态递减sp。只需使用减法指令,如
sub esp, eax
,其中您已经在eax
中建立了动态递减量。如果您这样做,则新数组将从esp
中的地址开始。问题是,在知道输入了多少项之前,您无法计算递减量。
因此,如果在用户要求停止之前,你不知道有多少项,那么你可以在输入时将单个项压入堆栈,但结果数组中的元素将按记忆顺序反向排列--所以,你可以稍后用一个简单的循环将它们反向排列,或者如果程序的其余部分不太复杂的话,选择按反向顺序工作。
这种方式使用堆栈会因为对齐要求而变得更加复杂。首先,x86的对齐大于一个整数,因此在函数调用之前,有时需要在堆栈上填充,例如
printf
。其次,如果数组的元素大小小于一个整数,例如一个字节或8位字符,则压入会将填充引入到全整数大小。因此堆栈上的项不仅在内存中向后排列,而且还通过填充展开。由于堆栈的这些复杂性,通常使用其他解决方案:固定大小缓冲区或可扩展数组。
对于固定大小的缓冲区,只需要分配比所需更多的空间即可。因此,为128个元素分配空间(满足对齐)。如果遇到超过此数量的元素,可以简单地停止程序并显示错误消息。
对于可扩展数组,要添加元素,分配更多的存储空间,并将现有的拷贝到更大的新存储空间中。有多种技术可以减少拷贝数,作为速度和空间的折衷。这种方法通常使用堆内存而不是堆栈。