함수와 자동 변수
스택 조작
함수 호출과 자동 변수
- 함수 호출과 자동 변수는 스택을 사용합니다.
- 자동 변수는 함수 내부에서 선언된 변수입니다.
- 스택 사용은 플랫폼마다 다르며, 애플리케이션 바이너리 인터페이스(ABI)의 일부입니다.
- 스택 메모리는 암묵적으로 할당됩니다.
스택
스택의 구조
- 스택은 메모리에서 아래 방향으로 성장합니다.
- 스택의 베이스는 높은 주소에 위치하며, 스택의 꼭대기는 낮은 주소에 위치합니다.
스택 연산
- push: 스택의 꼭대기를 아래로 이동하여 항목을 위한 공간을 만들고, 해당 항목을 꼭대기에 배치합니다.
- pop: 스택의 꼭대기를 위로 이동시켜 항목을 제거합니다.
- 스택은 후입선출(LIFO) 방식으로 작동합니다: 가장 최근에 푸시된 항목만 팝할 수 있습니다.
변수 선언
변수 선언의 역할
- 변수 선언은 두 가지 기능을 수행합니다:
- 컴파일러에게 데이터를 위한 스택 공간을 예약하도록 요청합니다.
- 해당 데이터의 위치에 이름을 부여합니다.
예시
int array[32];
- "32개의 정수를 위한 공간을 만들고, 그 공간을 array라고 부르세요."
자동 변수
- 모든 지역 변수는 자동 변수입니다.
- 자동 변수는 참조되기 전에 할당이 보장됩니다.
- 해당 블록이 완료될 때까지 유효합니다.
자동 변수의 수명과 위치
자동 변수의 수명
- 함수가 입력될 때 자동 변수가 생성됩니다.
- 스택에 자동 변수를 배치하면 이러한 동작이 가능해집니다.
자동 변수의 위치
- 자동 변수는 어디에나 할당될 수 있습니다.
- 프로그래머는 변수의 순서나 위치를 예측할 수 없습니다.
- 변수는 레지스터에 있을 수도 있습니다.
- 변수의 구조는 보존됩니다.
함수 호출과 스택 프레임
함수 호출
- 가장 간단한 함수 호출은 다음과 같은 단계로 이루어집니다:
- 새로운 프로그램 위치로 점프
- 함수 코드 실행
- 호출 위치로 돌아가기
복잡한 함수 호출
- 함수 호출은 종종 자동 변수를 할당하고, 다른 함수를 호출하며, 레지스터를 임시로 저장합니다.
- 이러한 경우, 함수는 스택 프레임을 필요로 합니다.
스택 프레임
- 스택 프레임은 단일 함수 호출에 대한 정보를 저장합니다.
- 스택 프레임에는 다음이 포함됩니다:
- 저장된 프로세서 레지스터
- 현재 함수의 지역 변수
- 호출된 함수의 인수
- 호출된 함수의 반환 위치
지역 변수
함수의 지역 변수
- 함수의 모든 지역 변수는 종종 함께 할당됩니다.
- 함수가 시작될 때, 스택 꼭대기를 이동하여 로컬 스토리지를 위한 공간을 만듭니다.
- 이 스택 프레임 부분은 고정 크기입니다.
- 크기는 프로그램 명령에 의해 컴파일러에 의해 기록됩니다.
- 개별 변수의 위치도 기록됩니다.
함수 인수
인수 전달
- 플랫폼의 ABI가 인수 전달 방식을 결정합니다.
- 일반적으로 레지스터와 스택 공간의 조합입니다.
- 예를 들어, x86-64 Linux에서는 첫 6개의 64비트 값이 레지스터로 전달됩니다.
- 추가 인수는 스택에 푸시됩니다.
- 많은 함수는 스택에 인수가 없습니다.
함수 인수의 레이아웃
- 함수 인수가 스택에 푸시되는 경우, 일반적으로 역순으로 푸시됩니다.
- 첫 번째 함수 인수가 꼭대기와 가장 가깝습니다.
- 이는 가변 인수의 허용을 돕습니다.
프로그램 카운터
함수 호출 스택과 프로그램 카운터
- 프로그램 카운터는 현재 실행 중인 기계 명령의 주소입니다.
- 함수 호출 시:
- 현재 프로그램 카운터가 호출된 함수로 점프하기 전에 푸시됩니다.
- 호출된 함수는 반환하기 위해 프로그램 카운터를 팝합니다.
- 일부 아키텍처에는 이를 위한 전용 명령이 있습니다.
추가 내용: 필기 노트 반영
스택 메모리 할당
- 스택의 한 칸은 32비트 크기입니다.
- 스택은 위에서부터 아래로 증가할 때 한 칸씩 증가합니다.
- 스택에는 패딩 바이트가 있어, 예를 들어 double 타입의 변수가 온다면, 2칸이 아닌 3칸이 내려옵니다.
- 각 지역 변수에 접근할 때는 stack top을 이용합니다. 예:
top + 8.
- 컴파일러는 변수들이 stack top으로부터 얼마나 떨어져 있는지 알려줍니다.
스택 팝
- 스택을 팝해서 없애는 것은 각 메모리를 0으로 쓰는 것이 아닙니다.
- 실제로는 메모리를 0으로 초기화하지 않고, 스택 포인터만 이동합니다.
- 이로 인해 스택에서 제거된 항목은 지워지지 않고 남아있을 수 있습니다.
함수 호출
- 함수는 원하는 만큼 호출할 수 있지만, 한 번에 두 개의 함수를 동시에 호출할 수는 없습니다.
- 함수 호출 시, 이전 함수로 돌아가는 순간의 컨텍스트를 저장합니다.
- 인수 전달 방식:
- 인수가 6개 이하일 경우, 레지스터를 사용하여 전달합니다.
- 6개 이상의 인수는 스택에 푸시하여 전달합니다.
- 함수가 호출되기 직전에 프로그램 카운터(PC) 값이 스택에 푸시됩니다.
- 함수가 반환될 때, 스택에서 PC 값을 팝하여 원래 위치로 돌아갑니다.
요약
- 자동 변수는 스택에 할당됩니다.
- 스택은 아래 방향으로 성장합니다.
- 스택에서 제거된 항목은 지워지지 않습니다.
- 스택 프레임은 함수 호출을 추적합니다.