함수 호출.
스택 프레임 구조
함수 호출 과정에서 할당되는 메모리 블록을 가리켜 스택 프레임이라 합니다.
sp 레지스터
스택에 데이터를 쌓거나 반환하기 위해 어느 위치까지 데이터를 저장했는지 기억해야 합니다.
이를 위해서 CPU 내에 sp라는(Stack Pointer) 레지스터가 존재합니다.
변수 선언시 sp가 가리키는 위치에 할당하기 때문에 sp 위치를 아래로 이동 시키는 것 만으로도 이전에 선언된 변수를 반환 가능합니다. (변수 할당 시 이전에 저장된 값들을 덮어씁니다.)
- 시작은 sp 레지스터가 0번지.
- 변수나 함수 호출을 할 때 마다 sp 레지스터가 해당 주소 번지에 값을 넣고 변수나 함수의 스택 프레임 크기만큼 이동합니다. (다음에 변수나 함수에 대한 주소 값을 넣어주기 위해서)
sp 레지스터의 문제점
- 스택에 메모리를 할당할 때 sp 값의 증가 분은 계산이 가능합니다. (할당된 스택 프레임 만큼 이동)
- 하지만 호출 완료된 함수를 빠져나오는 시점에서 함수 내에 할당된 메모리 공간을 반환하기 위해 스택 프레임 단위로 sp를 아래로 옮길 때는 문제가 됩니다. ⇒ 어느 범위 만큼 아래로 이동시키는지에 대해서 알 수 없기 때문입니다.
- 해당 문제점을 해결하기 위해서 fp(프레임 포인터 레지스터)가 있습니다.
프레임 포인터(Frame Pointer)레지스터
되돌아갈 sp 레지스터의 위치를 저장하는 레지스터.
프레임 레지스터의 문제점
- 함수의 호출이 중복되었을 때
fct1() 함수 내에 fct2() 함수가 호출된다면.
- fct1() 함수 호출 시 fct1() 함수가 호출되고 난 이후 돌아갈 8번지 주소를 fp 레지스터에 저장한다.
- fct1() 함수 내에서 fct2() 함수가 호출되면 fct2() 함수가 호출되고 난 이후 돌아갈 16번지 주소를 fp 레지스터에 저장한다.
- 기존에 fct1() 함수가 호출되고 돌아갈 주소가 덮어 씌워져 버립니다.
프레임 레지스터의 문제점을 해결하기 ⇒ 스택에 저장하기
함수 호출이 일어날 때마다 fp 레지스터에 저장된 값을 어딘가에 저장하면 됩니다.
함수 호출이 일어날 때마다 fp 레지스터에 저장되어 있는 값을 스택에 저장합니다.
프레임 포인터를 스택에 저장하는 단계
- fct2() 함수가 호출되기 이전에 sp 레지스터에는 주소 값으로 20번지가 들어가 있습니다. fct1() 함수 내부 스택 프레임 공간
- fct2() 함수가 호출되기 직전에 fp 레지스터에는 주소 값으로 8번지가 들어가 있습니다. fct1() 함수가 호출되고 돌아갈 sp 레지스터의 주소 값입니다.
- fct2() 함수가 호출되면서 fp 레지스터에 저장된 값(8)을 현재 sp 레지스터가 가리키는 위치인 20번지에 먼저 저장합니다.
- 이후 fct2() 함수 호출이 완료되어 반환하려고 할 때 fp 레지스터에 저장된 값을 참조해서 sp 레지스터의 값을 20으로 변경합니다. ⇒ fct2 함수의 스택 프레임을 반환하는 효과를 가집니다. ⇒ fp 레지스터는 20번지에 저장된 값인 8번지 값을 가지게 됩니다.
- sp 레지스터가 가리키는 위치(20번지)에 저장되어 있는 값을 fp 레지스터에 옮겨 놓습니다. fp 레지스터는 20번지에 저장된 값인 8번지 값을 가지게 됩니다.
- fct1()함수 호출이 완료되면 fp 레지스터에 저장된 값을 참조하여 sp 레지스터를 8으로 변경 ⇒ fct1() 함수의 스택 프레임을 반환하는 효과를 가집니다. ⇒ fp 레지스터는 8번지에 저장된 0번지 값을 가지게 됩니다.
함수 호출 규약
함수 호출 규약이란?
- 함수 호출 시 전달되는 인자를 전달하는 방식
- 함수 호출 과정에서 할당된 스택 프레임을 반환하는 방법
- 위 두가지 방식을 약속해 놓은 것을 함수 호출 규약이라고 합니다.
- 함수 호출 시 정해진 규약이 없다면 프로젝트 속성창에서 디폴트 선언을 지정할 수 있는데 해당 디폴트 선언을 따르게 됩니다.
호출규약의 종류와 의미
- __cdcel : C/C++ 디폴트 호출 규약, 인자 전달 시 오른쪽 부터 스택에 쌓입니다. 반환 시에는 함수를 호출하는 호출자가 스택 프레임을 반환합니다. 함수를 호출한 주체에서 해당 함수의 스택 프레임 반환에 대한 처리를 진행합니다.
- __stdcall : 호출된 함수 내에서 스택 프레임을 반환하도록 정의되어 있습니다. 함수를 호출한 주체에서는 스택 프레임 반환 작업을 하지 않습니다.
- __fastcall : 함수 호출을 빠르게 처리하기 위한 규약입니다. 레지스터를 사용하여 함수 호출을 빠르게 처리합니다.
콜백 함수
Windows 시스템에 의해 자동으로 호출되는 함수를 의미합니다. 특정 상황에서 호출되어야 할 함수를 등록시키는 것이 가능한데, 이때 등록되는 함수를 가리켜 콜백함수라고 합니다.
참고(뇌를 자극하는 윈도우즈 시스템 프로그래밍)
https://www.hanbit.co.kr/store/books/look.php?p_code=B7673779595
뇌를 자극하는 윈도우즈 시스템 프로그래밍
이 책은 거의 모든 개발자가 궁금해 하면서도 또한 상당히 어려워하는 컴퓨터 구조, 운영체제, 시스템 프로그래밍의 내용 중 꼭 필요한 부분만 간추려서 담았다. 컴퓨터 구조와 운영체제에 대한
www.hanbit.co.kr
'CS' 카테고리의 다른 글
큐 (0) | 2025.02.08 |
---|---|
스택 (0) | 2025.01.26 |
리스트의 종류 (링크드, 더블 링크드, 환형 링크드) (0) | 2025.01.19 |
리스트 (0) | 2025.01.12 |