I wrote a simple program that takes an array length, populate the array by storing it at using esp decrement (so on the stack) then it print the array. My code is the following:
.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_input_format
call scanf
add esp,8
mov eax, [input_value]
push eax
dec edi
jnz array_input
mov edi,[input_length]
sub esp,4
print_array:
mov edx,[esp+4*edi]
push edx
push offset str_format_print
call printf
add esp,8
dec edi
jnz print_array
add esp,4
pop ebp
invoke ExitProcess,0
main ENDP
end
As you can see before the "print_array" part I need to sub esp by 4 because otherwise I get the current return address printed as the first element of the array (because it will be "esp+20" and the array starts at "esp+16") instead of the last element printed. After the part I add 4 to esp to get it to the right position again. Is that the correct way to print the array or there is another method instead of sub/add esp by 4 before/after the code part?
Also if I want to save the array on the Heap, how can I do it? I know I need to declare a variable, but this variable should have dynamic length because the length of the array is dynamic so I don't know how to get this:/
As you can see before the "print_array" part I need to sub esp by 4 because otherwise I get the current return address printed as the first element of the array (because it will be "esp+20" and the array starts at "esp+16") instead of the last element printed.
Your offsets tell me that you inputted 5 numbers for the array. Your stack will have looked like:
5,0,0,0,4,0,0,0,3,0,0,0,2,0,0,0,1,0,0,0,x,x,x,x,y,y,y,y
^ ^ ^
ESP Old EBP Return address
Without sub esp, 4
you would have retrieved the preserved value of EBP and not the current return address as you say.
After the part I add 4 to esp to get it to the right position again. Is that the correct way to print the array or there is another method instead of sub/add esp by 4 before/after the code part?
There's no wrong of right here, but you could have solved it without sub
/ add
if you would have added a correcting displacement of -4 to the instruction that loads EDX:
mov edi, [input_length] print_array: mov edx, [esp + 4*edi - 4]... dec edi jnz print_array
or if you would have considered array indexes to be zero-based quantities:
mov edi, [input_length]; eg. Array has 5 elements dec edi; eg. Highest element has index 4 print_array: mov edx, [esp + 4*edi]... dec edi; Lowest element has index 0 jns print_array; Continue for all positive indexes
Also if I want to save the array on the Heap, how can I do it?
If you need to go that way then read about it in Dynamic Heap Memory in x86 Assembly MASM .
Below is a version of the code that allocates the required space for the array on the stack in a single operation, and that stores the array elements in the normal order (which is easier to work with):
push ebp
mov ebp, esp
; Prompt for the number of elements
push offset str_insert_array_length
call printf
push offset input_length
push offset str_input_format
call scanf
add esp, 4 + 8 ; Combining both clean-ups
; Make room on the stack based on the number of elements
mov eax, [input_length] ; eg. 5
shl eax, 2 ; Is times 4 (size of integer)
sub esp, eax ; eg. Minus 20
; Input the elements in the space between ESP and EBP
mov edi, esp
array_input:
push offset str_insert_value
call printf
push edi ; No need to go via an extra variable!
push offset str_input_format
call scanf
add esp, 4 + 8
add edi, 4
cmp edi, ebp
jb array_input
; Print the elements from the space between ESP and EBP
mov edi, esp
print_array:
mov edx, [edi]
push edx
push offset str_format_print
call printf
add esp, 8
add edi, 4
cmp edi, ebp
jb print_array
pop ebp
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.