함수 호출 규약은 다른 2개의 프로젝트를 연결할 때 사용되는 개념으로 dll 등을 제작할 때 필요하다.
함수를 호출할 경우에는 호출하는 쪽에서 파라미터로 data를 전달하고, 함수에서는 그 data로 여러 처리를 하는데
이때 파라미터의 전달 방법 그리고 전달된 파라미터를 해제하는 방법이 여러가지가 있다. 이를 함수 호출 규약이라고 한다.
호출 규약에는 __stdcall, __cdecl, __fastcall, __thiscall 등 여러가지 종류가 있다.
__stdcall
__cdecl
C/C++ 의 기본 호출 방식이다.
__fastcall
이름 그대로 빠른 호출 규약이다. Windows API 는 이 호출 규약을 지원하긴 하지만 사용하진 않는다.
__thiscall
클래스의 멤버 함수에 대해서만 적용되는 호출규약으로 ecx 로 객체의 포인터(this)가 전달된다는 것이 특징이다.
그 외 규칙은 __stdcall과 동일하다.
가변인수를 사용하는 멤버 함수는 __cdecl으로 작성되며 이때 this는 스택의 제일 마지막에 (그러므로 첫 번째 인수에) 전달된다.
__naked
이 호출 규약은 컴파일러가 접두, 접미를 작성하지 않기 때문에 사용자가 직접 접두, 접미를 작성해야 한다.
함수 호출 규약의 주된 차이점은 스택 정리하는 곳이다.
호출한 쪽(Caller)에서 정리하는 방식은 파라미터로 전달한 인자의 개수를 알 수 있기 때문에 가변 인자 함수를 지원한다는 것이다.
__stdcall 은 함수가 직접 스택을 정리하기 때문에 가변인수 함수를 지원하지 않는다.
함수 접미에 스택 정리 코드를 작성하려면 인수의 총 크기를 미리 알아야 하는데 가변 인수 함수는 전달되는 인수 개수가 가변이므로 크기가 고정적이지 않아 접미에서 스택을 직접 정리할 수 없다. 컴파일러가 접미의 명령에 대해 결정할 수 없는 것이다.
이에 비해 __cdecl은 함수를 호출한 부모에서 스택을 정리하기 때문에 함수를 호출하는 쪽에서 인수를 몇개 전달했는지 알 수 있다.
호출 규약 중 호출원이 스택을 정리하는 것은 __cdecl 밖에 없으며 때문에 가변인수를 지원하는 호출규약도 __cdecl이 유일하다.
__cdecl을 제외한 나머지 모두는 호출당한 자함수(Callee)에서 정리한다. 그 이유는 속도 때문이다.
__cdecl 는 add 명령어를 통해 호출한 후에 스택을 정리한다. add 명령어를 호출하기 때문에 근소한 속도차이가 발생한다.
[참조] http://blog.naver.com/psj5500/140117467857
http://www.winapi.co.kr/clec/cpp2/16-1-3.htm
http://www.jiniya.net/lecture/techbox/callconv.html
'프로그래밍' 카테고리의 다른 글
glsl (0) | 2013.10.10 |
---|---|
코드 예쁘게 (0) | 2013.10.07 |
error LNK1104: cannot open file 'dxerr9.lib' (1) | 2013.02.03 |
[AI] FSM (Finite State Machine : 유한 상태 기계) (2) | 2013.01.23 |
GPG (0) | 2013.01.15 |