GCC Array

by Mithrandir

While doing one homework I’ve observed one little known fact about gcc: declaring dynamic arrays as normal arays (like int a[n])

I’ve decided to investigate this a little and wrote this small code:</p

#include <stdio.h>
#include <stdlib.h>

int f(int n)
{
#ifdef EXT
        int a[n];
#else
        int *a=calloc(5, sizeof(a[0]));
#endif
        a[2] = n;
        return a[2];
}

int main()
{
        printf("%d\n", f(5));
        return 0;
}

Compiling this code, looking at file sizes and testing it we obtain the following:

mihai@keldon:/tmp$ gcc -Wall -Wextra 1.c -S -o 1a.s && gcc 1a.s && ls -lh 1a.s a.out && wc -l 1a.s && ./a.out
-rw-r--r-- 1 mihai mihai  786 2010-05-01 11:14 1a.s
-rwxr-xr-x 1 mihai mihai 9.0K 2010-05-01 11:14 a.out
50 1a.s
5
 
mihai@keldon:/tmp$ gcc -Wall -Wextra 1.c -S -o 1b.s -DEXT && gcc 1b.s && ls -lh 1b.s a.out && wc -l 1b.s && ./a.out
-rw-r--r-- 1 mihai mihai 2.0K 2010-05-01 11:15 1b.s
-rwxr-xr-x 1 mihai mihai 9.0K 2010-05-01 11:15 a.out
116 1b.s
5

Let’s look at the generated assembly in each of the two cases. For 1a.s (normal case) we have:

        .file   "1.c"
        .text
.globl f
        .type   f, @function
f:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        movl    $4, 4(%esp)
        movl    $2, (%esp)
        call    calloc
        movl    %eax, -4(%ebp)
        movl    -4(%ebp), %eax
        leal    8(%eax), %edx
        movl    8(%ebp), %eax
        movl    %eax, (%edx)
        movl    -4(%ebp), %eax
        addl    $8, %eax
        movl    (%eax), %eax
        leave
        ret
        .size   f, .-f
        .section        .rodata
.LC0:
        .string "%d\n"
        .text
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $20, %esp
        movl    $5, (%esp)
        call    f
        movl    %eax, 4(%esp)
        movl    $.LC0, (%esp)
        call    printf
        movl    $0, %eax
        addl    $20, %esp
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
        .section        .note.GNU-stack,"",@progbits

The second file looks like this:

        .file   "1.c"
        .text
.globl f
        .type   f, @function
f:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %edi
        pushl   %esi
        pushl   %ebx
        subl    $44, %esp
        movl    %gs:20, %eax
        movl    %eax, -20(%ebp)
        xorl    %eax, %eax
        movl    %esp, %eax
        movl    %eax, %edi
        movl    8(%ebp), %esi
        movl    %esi, %eax
        movl    %eax, -56(%ebp)
        movl    $0, -52(%ebp)
        movl    -56(%ebp), %eax
        andb    $255, %ah
        movl    -52(%ebp), %edx
        andl    $15, %edx
        movl    %eax, -56(%ebp)
        movl    %edx, -52(%ebp)
        movl    -56(%ebp), %ecx
        movl    -52(%ebp), %ebx
        shldl   $5, %ecx, %ebx
        sall    $5, %ecx
        movl    %ecx, %eax
        andb    $255, %ah
        movl    %ebx, %edx
        andl    $15, %edx
        movl    %eax, %ecx
        movl    %edx, %ebx
        movl    %esi, %eax
        movl    %eax, -48(%ebp)
        movl    $0, -44(%ebp)
        movl    -48(%ebp), %eax
        andb    $255, %ah
        movl    -44(%ebp), %edx
        andl    $15, %edx
        movl    %eax, -48(%ebp)
        movl    %edx, -44(%ebp)
        movl    -48(%ebp), %ecx
        movl    -44(%ebp), %ebx
        shldl   $5, %ecx, %ebx
        sall    $5, %ecx
        movl    %ecx, %eax
        andb    $255, %ah
        movl    %ebx, %edx
        andl    $15, %edx
        movl    %eax, %ecx
        movl    %edx, %ebx
        movl    %esi, %eax
        sall    $2, %eax
        addl    $15, %eax
        addl    $15, %eax
        shrl    $4, %eax
        sall    $4, %eax
        subl    %eax, %esp
        movl    %esp, -36(%ebp)
        movl    -36(%ebp), %eax
        addl    $15, %eax
        shrl    $4, %eax
        sall    $4, %eax
        movl    %eax, -36(%ebp)
        movl    -36(%ebp), %edx
        movl    %edx, -24(%ebp)
        movl    -24(%ebp), %edx
        movl    8(%ebp), %eax
        movl    %eax, 8(%edx)
        movl    -24(%ebp), %eax
        movl    8(%eax), %eax
        movl    %edi, %esp
        movl    -20(%ebp), %edx
        xorl    %gs:20, %edx
        je      .L3
        call    __stack_chk_fail
.L3:
        leal    -12(%ebp), %esp
        popl    %ebx
        popl    %esi
        popl    %edi
        popl    %ebp
        ret
        .size   f, .-f
        .section        .rodata
.LC0:
        .string "%d\n"
        .text
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $20, %esp
        movl    $5, (%esp)
        call    f
        movl    %eax, 4(%esp)
        movl    $.LC0, (%esp)
        call    printf
        movl    $0, %eax
        addl    $20, %esp
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
        .section        .note.GNU-stack,"",@progbits

Right now, I have some questions:

  • I observed that this declaration doesn’t work in main. Can someone explain why?
  • Is this a gcc extension or it is in the standards (too lazy now to boot up my Windows VM and test with cl)
  • More questions will follow

    About these ads