스택 프레임
int result = MultiPlayBy(b, a) 라고 한다면,
어셈블리 언어로 까보면 오른쪽부터 a를 먼저 push해준다.
지역 변수와 값 전달
데이터 영역에 .rodata, .data, bbs 세가지 영역이 있었음. 초기화 여부, const 등 세부사항에 따라 각 영역에 할당됨
호출스택에서 스택프레임이 구성되는 건 [매개변수][RET][지역변수]
사실 스택이란거 자체는 처음부터 충분히 큰 공간을 할당을 해놓고 시작을 한다. 거기서 각기 함수들이 원하는 영역만큼을 찝어가지고 사용한다.
[매개변수][RET] 세팅은 이전 함수에서 정해서 넘겨주게 된다. 지역변수는 온전히 자기 자신이 제어한다.
void IncreaseHP(int hp)
{
int finalHP = hp + 1;
}
// [매개변수][RET][지역변수(hp=1)] [매개변수(hp=1)][RET(0x00ABCA5)][지역변수(finalHP=2)]
int main()
{
int hp = 1;
IncreaseHP(hp);
}
이를 통해 알수있는 건, 함수를 통해 다른값을 넘길 때, 그 변수를 넘기는 것 같지만 이는 눈속임이다. 정확히 데이터의 값을 복사해 넘기고있다.
RET 리턴주소는 함수 call을 하는 순간, 내 리턴주소를 넣어준 다음에, 상대방 함수의 시작주소로 넘어가서 시작한다. 함수가 끝나는 순간 아까 call 할 때, 넣어뒀던 리턴주소로 가서 다시 시작한다.
호출 스택
반환 주소값들을 하나씩 참조해보면 호출 스택을 알 수 있다.
하지만 그렇다고 디스어셈블리를 보거나 레지스터를 매번 보면 말이 안된다.
그래서 디버거를 통해 호출스택 창을 통해 바로 알 수 있다.
함수 마무리
디폴트 매개변수 중 C#은 골라서 매개변수 네임드를 지칭해서 초기화할 수 있어서 문법을 안지킬 수 있는데 C++은 지켜줘야한다.
번외
디폴트 매개변수를 메모리 구조 때문이라기 보다는 순전히 문법적인 이유가 강하다.
(어셈블리 관점에서 ‘디폴트 매개변수’라는 개념은 존재하지도 않다.)
Func(int c = 0, int a, int b)와 같은 형태면 만약 Func(100, 200) 이렇게 해버리면 c의 자리에 100, a = 200, b는 입력 안 한 상태가 된다.
따라서 기본 매개변수가 들어가는 함수는 뒤쪽으로 몰빵하게 문법이 만들어진 것이다.
'Script > C++' 카테고리의 다른 글
[C++] Chapter 06. 함수 포인터 (0) | 2023.05.12 |
---|---|
[C++] Chapter 05. 크러쉬가 나는 오작동 현상 (0) | 2023.05.12 |
[C++] Chapter 04. 객체지향 여행 (0) | 2023.05.12 |
[C++] Chapter 03. 포인터#2 (포인터 vs 배열) (0) | 2023.05.11 |
[C++] Chapter 02. 포인터#1 (기초, Reference) (1) | 2023.05.11 |
댓글