호출규약
호출규약은 호출원과 함수간의 약속이므로 양쪽이 다른 형태로 약속을 할 수도 있는 것이다.
호출 규약 |
인수 전달 |
스택 정리 |
이름 규칙 |
__cdecl |
오른쪽 먼저 |
호출원 |
_함수명 |
__stdcall |
오른쪽 먼저 |
함수 |
_함수명@인수크기 |
__fastcall |
ECX, EDX에 우선 전달. 나머지는 오른쪽 먼저 |
함수 |
@함수혐@인수크기 |
thiscall |
오른쪽 먼저, this 포인터 ecx레지스터로 전달된다. |
함수 |
C++ 이름 규칙을 따름. |
naked |
오른쪽 먼저 |
함수 |
없음 |
__stdcall
__stdcall은 윈도우즈 API 함수들의 기본 호출을 규약을 사용한다. __cdecl과 인수를 전달하는 방법은 동일하되 인수 전달에 사용된 스택을 정리하는 주체가 호출원이 아니라
함수라는 점이 다르다. 함수의 이름 앞에 __stdcall 키워드를 붙이면 호츌 규약을 사용한다.
__cdecl과의 차이점
__cdecl과 __stdcall의 가장 큰 차이점은 스택 정리 주체가 누구인가하는 점인데 사실 이 차이점이 컴파일된 결과 코드에 미치는 영향은 별로 없다. 스택 정리 주체와는 상관없이 스택은 항상 호출 전의 상태로 복구되며 프로그램의 동작도 완전히 동일하다. 실행 속도는 거의 차이가 없으며 프로그램의 크기는 비록 무시할만한 수준이기는 하지만 __stdcall이 조금 더 작다. 이유는 함수를 여러 번 호출하더라도 스택을 정리하는 코드는 함수 끝의 접미에 딱 한 번만 작성되기 때문이다.
__fastcall
__fastcall은 전달을 위해 edx, ecx 레지스터를 사용하는데 두 개의 인수를 차례대로 edx, ecx에 대입했다. 만약 인수가 둘 이상이면 세 번째 이후의 인수는 __cdecl과 마찬가지로 스택에 밀어넣을 것이다. 인수 전달을 위해 스택을 쓰지 않고 레지스터를 우선적으로 사용하므로 인수 전달 속도가 빠르다는 이점이 있다.
__thiscall
클래스의 멤버 함수에 대해서만 적용되는데 ecx로 객체의 포인터가 전달된다는 것이 특징이며 나머지 규칙은 __stdcall과 동일하다. 예외적으로 가변 인수를 사용하는 멤버 함수는 __cdecl로 작성되며 이때 this는 스택의 제일 마지막(첫 번째 인수로)에 전달된다.
__naked
__naked 호출 규약은 컴파일러가 접두, 접미를 작성하지 않는 호출 규약이다. 스택 프레임의 상태 보존을 위해 컴파일러가 어떤 코드도 작성하지 않으므로 접두, 접미는 사용자가 직접 작성해야 한다. 스택은 어셈블리 수준에서만 다룰 수 있으므로 인라인 어셈블리를 사용해야 하며 제약점도 많기 때문에 일반적인 목적으로는 사용되지 않는다.
이 호출 규약이 반드시 필요한 경우는 C/C++이 아닌 언어에서 호출하는 함수를 작성할 때이다. 예를 들어 어셈블리에서는 인수 전달에 스택을 쓰지 않고 범용 레지스터만으로도 인수를 전달할 수 있다. 이런 경우는 C컴파일러가 만들어주는 접두, 접미가 불필요하다. 또한 속도가 지극히 중요한 디바이스 드라이버를 작성할 때도 이 호출 규약을 사용한다.
출처 : 혼자연구하는 C/C++
'Program Languege > C/C++' 카테고리의 다른 글
얕은 복사, 깊은 복사 (0) | 2014.03.13 |
---|---|
Console (0) | 2014.03.05 |
const의 선언 위치 (0) | 2014.02.20 |
템플릿 - 4 (0) | 2013.03.19 |
템플릿 - 3 (0) | 2013.03.19 |