챕터 6-2 : [심화] 스택 프레임
수업 목표
- 함수의 호출 비용에 대해서 알아본다.
- 스택 메모리에 대해 배워본다.
함수는 몇 회나 호출될 수 있을까요?
함수의 호출 횟수는 제한 할 수 없습니다. 심지어 게임의 중추가 되는 어떤 함수(Tick() 함수 같은)는 1초에 수천번씩 호출될 수도 있습니다. 롤과 같은 게임을 하면 FPS 값을 알 수 있습니다. 60 프레임이라면, 어떤 함수는 1초에 60번 호출되고 있는 것입니다. 그렇기에 함수의 호출 비용은 최대한 적어야 합니다.
함수의 호출 비용을 최대한 줄이려면.
함수는 결국 코드 뭉치라고 했습니다. 함수 A에서 함수 B를 호출하면 함수 A 코드 뭉치에 함수 B 코드 뭉치를 쌓아 올렸다가, 종료되면 함수 B 코드 뭉치를 없애면 됩니다. 이걸 빠르고 호출 비용이 저렴하게 처리해야 합니다. 이를 1초에 수만번씩해도 빠르게 처리 해주는 자료구조가 스택입니다. 군필자라면 탄알집을 생각하시면 됩니다. 나중에 넣은 탄알이 먼저 나오는 자료구조입니다. 수건함 같은 느낌. 굳이 맨 밑 수건을 꺼내면 엄마한테 혼납니다. 가장 위에 있는 수건이 가장 먼저 나오는 구조입니다.
스택 메모리(Stack Memory)
컴퓨터의 메모리 레이아웃은 크게 스택 메모리, 힙 메모리, 코드 섹션, 데이터 섹션으로 나뉩니다.
그 중에서 스택 메모리는 함수 호출에 할당될 메모리입니다. 결국 지역변수들이 저장되는 공간입니다.
스택 메모리는 스택 포인터와 베이스 포인터, 스택 프레임들로 구성되어 있습니다.

스택 프레임(Stack Frame)
함수가 호출되면 해당 함수가 사용할 메모리 크기만큼 공간이 확보됩니다.
해당 함수를 위해 확보된 메모리 공간을 스택프레임이라고 합니다.
나중에 함수가 모두 수행된 뒤에 해당 스택프레임은 다시 반환됩니다.
Ex060201) [참고] 스택프레임의 동작
[참고] 스택 포인터(Extended Stack Pointer, ESP)
현재 스택 프레임의 Top을 가르킵니다. push 명령어나 pop 명령어의 피연산자.
[참고] 베이스 포인터(Extended Base Pointer, EBP)
현재 스택 프레임의 시작 주소를 가르킵니다.
아래 소스코드를 어셈블리 코드로 만들어봅시다.
해당 어셈블리 코드를 통해 스택프레임의 생성 및 파괴 과정을 천천히 살펴봅시다.
// Main.c
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int main(void)
{
int res;
res = add(2, 5);
return 0;
}
# 보기 좋게 정리한 어셈블리 코드입니다. 정확하지 않을 수도 있습니다.
# 스택프레임이 어떻게 생성되고 지워지는지만 확인해보세요!
_main: # @main
pushl %ebp # esp -= 4하고 [esp] = ebp
movl %esp, %ebp # ebp = esp
subl $16, %esp # esp -= 16 (로컬 변수 공간 확보)
...
call _add # add() 함수 호출
...
addl $16, %esp # esp += 16 (스택 정리)
popl %ebp # ebp = [esp]하고 esp += 4
ret
_add: # @add
pushl %ebp # esp -= 4, [esp] = ebp
movl %esp, %ebp # ebp = esp
subl $36, %esp # esp -= 36
...
addl $36, %esp # esp += 36
popl %ebp # ebp = [esp]하고 esp += 4
ret
<?> 어셈블리어 이해가 어려움



<?> 위에 한 공간은 왜 남기는걸까
스택프레임 개념은 아주 중요합니다.
프로그래밍을 계속 하게 된다면, 스택프레임 관련된 내용은 계속해서 나옵니다.
사람들이 어렵다고 생각하는 개념들 거의 대부분이 스택프레임과 관련있기도 합니다.
프로그래밍을 처음해본다면, 일단은 넘어가도 좋습니다.