- 함수를 호출하는 방식에 대한 일종의 약속
- 인수는 어떻게 전달하며 리턴값은 어떻게 반환하고 인수 전달을 위해 사용한 메모리는 누가 정리할 것인지를 규정함.
- 호출하는 쪽과 호출되는 쪽의 약속이 맞아야 한다.
- 컴파일러 내부에서 일어난다.
| 호출 규약 | 인수 전달 | 스택 정리 | 이름 규칙 |
| __cdecl | 오른쪽 먼저 | 호출원 | _ 함수명 |
| __stdcall | 오른쪽 먼저 | 함수 | _함수명@인수크기 |
| __fastcall | ECX, EDX에 우선 전달, 나머지는 오른쪽 먼저 | 함수 | @함수명@인수크기 |
| thiscall | 오른쪽 먼저, this 포인터는 ecx 레지스터로 전달된다. | 함수 | C++ 이름 규칙 따름 |
| naked | 오른쪽 먼저 | 함수 | 없음 |
(1) __cdecl
- C 컴파일러 혹은 C++ 컴파일러에서 전역 함수나 전역 static 함수, static 멤버 변수 호출에 기본적으로 사용하는 규약.
- 가변 인수를 지원
- 리턴값은 eax를 통해서 되돌려 받음.(다른 규약도 동일함)
(2) __stdcall
- 윈도우즈 API 함수들의 기본 호출 규약.(비주얼 베이직도 사용)
- __cdecl과 인수를 전달하는 방법은 동일하되 인수 전달에 사용된 스택을 정리하는 주체가 호출원이 아니라 함수라는 점이 다르다.
- 함수 이름 앞에 __stdcall 키워드를 사용하면 이 함수는 __stdcall 호출 규약을 사용한다.
- 가변 인수를 지원하지 않는다.
(3) __fastcall
- 인수 전달을 위해 스택을 쓰지 않고 레지스터를 우선적으로 사용하므로 인수 전달 속도가 빠르다
- 비주얼 C++은 fastcall을 형식적으로 지원할 뿐 fastcall의 장점을 취하진 않는다.(컴파일러 구현상 ecx, edx 레지스터가 꼭 필요하기 때문임)
- 이식성에 불리하다.(ecx, edx 레지스터를 사용하지 않는 CPU에서는 지원 안함)
- 볼랜드의 델파이가 __fastcall을 사용함.
(4) thiscall
- 클래스의 멤버 함수에 대해서만 적용됨.
- ecx로 객체의 포인터(this)가 전달되는 특징이 잇다.
- 나머지 규칙은 __stdcall과 동일함.
- 예외적으로 가변 인수를 사용하는 멤버 함수는 __cdecl로 작성되면 이때 this는 스택의 제일 마지막에(그러므로 첫번째 인수로) 전달된다.
- 이 호출 규약은 컴파일러가 멤버함수에 대해서만 적용하는 것이므로 일반 함수에는 이 호출 규약을 적용할 수 없다.(thiscall 키워드가 아님.)
(5) __naked
- 컴파일러가 접두, 접미를 작성하지 않는 호출 규약.
- 일반적인 목적으로는 사용되지 않음.
- C/C++이 아닌 언어에서 호출하는 함수를 작성할 때 필요함.
- 속도가 지극히 중요한 디바이스 드라이버를 작성할 때도 사용함.
- __naked 호출 규약을 사용하려면 함수의 정의부에 __declspec(naked)를 적어주면 된다.
(6) 기타(__pascal, __fortran, __syscall)
* __cdecl과 __stdcall의 차이점
- 누가 스택을 정리하느냐
- stdcall의 경우 호출된 함수(Callee)가 스택을 정리하기 때문에 호출하는 함수(Caller)와 Callee 모두 파라미터의 크기를 알고 있어야 정상적인 처리가 가능하다.
- cdecl의 경우 Caller가 스택을 정리하기 때문에 Callee는 파라마티의 크기를 정확히 몰라도 된다.