본문 바로가기
Script/C++

[C++] Chapter 01. 함수

by song.ift 2023. 5. 11.

스택 프레임

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는 입력 안 한 상태가 된다.

따라서 기본 매개변수가 들어가는 함수는 뒤쪽으로 몰빵하게 문법이 만들어진 것이다.

댓글