Suppose the size of an integer array is stored in eax. I suppose you can you can allocate memory for the array like so:
subl (%eax), %esp
However, the size in eax is provided by the user and will be a different size with each program execution. Given this, how could initialize each 4 byte memory address with an integer supplied by the user with scanf? How can we ensure that if more integers are supplied than the size of the array, we don't overwrite any memory?
subl (%eax), %esp
reads the content of the address denoted by the value of eax
.
This is most likely something you don't want to do in this context.
If eax
is the size in bytes of the array then subl %eax, %esp
will allocate enough memory for it.
If eax
is the number of 32-bit integers of the array then leal (,%eax,4), %esp
is the correct instruction.
None of the instructions above account for the alignment of the stack.
In order to correctly return from your procedure you must be able to correctly undo the steps above - keep track of the quantities that you need to perform this.
You can access the items of the array through the frame pointer, if any, or directly as positive offset from esp
.
Regarding your other questions - Those are really ordinary C questions, any C tutorial covers such topics.
If you are at a dead end when switching from C to assembly, you can let a compiler inspire you.
Below is the code generated by GCC for a function that resemble the one you want to implement (as I've understood it):
#include <stdio.h>
void foo(int n)
{
int arr[n];
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
}
.LC0:
.string "%d"
foo(int):
pushl %ebp
movl %esp, %ebp ;Prologue
pushl %edi
pushl %esi
movl 8(%ebp), %edi ;EDI = n
pushl %ebx
leal 4(,%edi,4), %eax ;EAX = n*4+4 (For alignment purpose)
subl %eax, %esp ;Allocate space
;Pre loop condition
testl %edi, %edi
jle .L1
;Loop init
movl %esp, %esi ;ESI = ptr to first element
xorl %ebx, %ebx ;EBX = Counter
.L5:
;scanf("%d", &arr[i]);
pushl %esi
pushl $.LC0
addl $1, %ebx ;Inc counter
addl $4, %esi ;Move pointer
call scanf
;Loop condition
cmpl %ebx, %edi
popl %eax
popl %edx
jne .L5
.L1:
leal -12(%ebp), %esp ;Deallocate
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
For the purpose of this answer I've assumed the existence of VLAs which is not mandatory in C11 and doesn't really map one-to-one to the capability of the assembly programmer to grow and shrink the stack.