sdfsdfsdf
sdfsdfsdf

Reputation: 49

How can you create an array of size x on stack and scanf values into it

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?

Upvotes: 0

Views: 394

Answers (1)

Margaret Bloom
Margaret Bloom

Reputation: 44066

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.

Upvotes: 3

Related Questions