Win32 - 함수 호출 규약
[TOC]
함수 호출 방법
- 정적함수 호출(전역함수, namespace 내의 전역함수, static 멤버 함수) : f();
- 객체로 멤버함수 호출 : a.f();
- 객체의 주소로 멤버 함수 호출 : a->f();
함수 호출 규약
- 함수 호출 시 전달되는 인자를 스택에 넣는 순서나 함수가 종료될 때 함수의 스택을 정리하는 시점 등을 약속한것.
종류
- cdecl(C declaration)
- C 프로그래밍 언어가 기원인 호출 규약으로서 x86 아키텍처용의 수많은 C 컴파일러가 사용한다.
- 스택에 함수 인자 푸시 : 오른쪽 -> 왼쪽
- 함수 종료 시 스택 정리의 주체 : calller
- pascal
- 파스칼 프로그래밍 언어의 호출 규약
- 스택에 함수 인자 푸시 : 왼쪽 -> 오른쪽
- 함수 종료 시 스택 정리의 주체 : calllee
- stdcall
- 마이크로소프트 Win32 API 및 오픈 왓콤 C++의 표준 호출 규약
- pascal 호출 규약의 변형
- 스택에 함수 인자 푸시 : 오른쪽 -> 왼쪽
- 함수 종료 시 스택 정리의 주체 : calllee
- fastcall
- fastcall은 표준화된 규약은 아니며 컴파일러 업체에 따라 다르게 처리된다.[1] 일반적으로 fastcall 호출 규약은 레지스터 내 하나 이상의 인수를 통과시키며 호출에 필요한 메모리 접근의 수를 줄인다.
- thiscall
- C++ 멤버 함수의 호출 규약으로 비정적 멤버 함수를 호출하는데 사용된다. 비정적이란 C++ 클래스의 멤버 함수를 만들 때 static 키워드를 주지않고 만든 경우(일반적인 경우)를 의미함. 만약, C++ 멤버 함수에 static 키워드가 주어지면 독립함수가 되며(단위함수:쓰레드 단위로 작동이 가능한 함수) 모체를 필요로하지 않게된다. 여기서 모체란 C++ 클래스가 메모리에 인스턴스화 되었을 때 가상함수 테이블 포인터 값을 갖고 있는 포인터인 this 포인터를 의미한다. 즉, static 키워드와 함께 멤버 함수를 만들면 일반 호출 규약을 따르는 독립함수가 되고 C++ 과 상관없는 독립함수가 되며 static 키워드가 없으면 모체에 종속적인 멤버 함수가 된다. 이때 모체종속 적인 함수들 즉, 종속적 비정적 멤버 함수들은 thiscall 호출 규약을 따르게 된다. thiscall 호출 규약은 this + call 이며 this 포인터를 넘기고 call 을 한다는 의미이다.
정적함수와 멤버함수의 호출 규약
정적 함수의 기본 함수 호출 규약은 cdecl, 멤버함수는 thiscall. 따라서 정적 함수와 멤버 함수 포인터를 다르게 선언함.
Windows에서 함수 호출 규약 정의
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
- 윈도우에서 사용하는 함수 호출 규약은 stdcall을 재정의한 CALLBACK, WINAPI, APIENTRY(API Entry)를 사용한다.
- 다른 이름으로 정의해서 사용하는 이유
- 함수의 용도를 명확히 하기 위해 사용용도에 맞은 이름으로 재정의하여 사용
- 콜백 함수를 나타내기 위해 CALLBACK을 사용
- 함수의 용도를 명확히 하기 위해 사용용도에 맞은 이름으로 재정의하여 사용
참고
- https://ko.wikipedia.org/wiki/X86%ED%98%B8%EC%B6%9C%EA%B7%9C%EC%95%BD
- https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types#winapi
- https://kldp.org/node/39210