stack 에서 esp 를 감소시킬때..

arimae의 이미지

함수를 호출할때 내부적으로 선언한 데이터의 크기만큼 esp 를 조정을 하게 되는데, gcc -S 를 이용해서 어셈 코드를 생성한 것을 보고 궁금한 점이 있어 글을 올립니다.

#include <stdio.h>

int main(int argc, char *argv[])
{
    int a;
    int b;
    int c;
    int d;

    return 0;
}

위의 경우에는 정상적으로 int 형의 크기 * 4 = 16 byte 만큼 esp에서 감소를 시킵니다. 단순히 int 형으로 하나씩 선언할 경우에는 선언이 하나 증가할때 마다 esp 에서 4씨 더 빼주게 됩니다.

        .file   "test3.c"
        .version        "01.01"
gcc2_compiled.:
.text
        .align 4
.globl main
        .type    main,@function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $16, %esp
        movl    $0, %eax
        leave
        ret
.Lfe1:
        .size    main,.Lfe1-main
        .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.1)"

다른 방법으로 이제 배열로 테스트 해봤더니 배열은 다른 결과가 나오더군요.
처음 int a[1], int a[2] 까지는 4, 8 byte 씨 esp 에서 빼다가 int a[3] 의 경우 12가 아닌 갑자기 24 byte를 빼더군요. 그리고 int a[4] 의 경우 역시 24byte 를 빼다가 int a[5] 에서는 40 byte를 빼게 됩니다. 즉 일정 간격마다 16 byte 씩 증가하게 됩니다.

#include <stdio.h>

int main(int argc, char *argv[])
{
    int a[5];

    return 0;
}

        .file   "test3.c"
        .version        "01.01"
gcc2_compiled.:
.text
        .align 4
.globl main
        .type    main,@function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $40, %esp
        movl    $0, %eax
        leave
        ret
.Lfe1:
        .size    main,.Lfe1-main
        .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.1)"

gcc 3.3.3 에서도 비슷하게 감소 되더군요.
main 함수 뿐만 아니라 일반 함수에서도 이런 현상이 발생하는데, 왜 이렇게 구현했는지 궁금합니다. 아마 일부러 gcc 에서 이렇게 만드는것 같은데, 보안 문제 때문이 아닐까 추측을 해보았지만, 정확한 답은 모르겠더군요.

어셈쪽에 지식이 얕아 이렇게 글을 올립니다. 잘 아시는 분의 명쾌한 답변 기다리겠습니다.

bugiii의 이미지

스택에 놓은 지역변수들의 접근성을 좋게 하기위해서 일부러 16바이트 정렬을 하는 것 같습니다.

함수 본체도 그런식으로 정렬하는 경우가 있죠. (대부분 그렇게 할겁니다.)

캐쉬가 그렇게 되어야 히트수가 높아지니까 성능상 이득이 많다고 알고 있습니다.

jyj9782의 이미지

넹 2.96 이전버전은 4바이트 정렬..
이후는 16바이트 정렬 .. 이라고 알고 있어요.
저런 성능상의 이유였군요.
고맙습니다

힘내세요.

arimae의 이미지

성능 상의 이유였군요.. 답변 주셔서 감사합니다.

Dream, Passion and Challenge..