본문 바로가기
Research/Programming

__cdecl을 사용하는 이유 ?

by sunnyan 2002. 12. 4.
728x90
대개의 언어들은 함수 또는 프로시져를 호출할 때 스택을 통해서 인자를 전달합니다. 이 때 인자를 전달하는 방식이 여러가지가 있을 수 있습니다. 예를 들어 첫번째 인자를 먼저 스택에 넣을 수도 있고, 아니면 마지막 인자를 먼저 스택에 넣을 수도 있겠죠. 또한, 스택에 넣은 인자를 누가 제거하느냐의 차이가 있을 수도 있습니다. (호출한 함수가 할 수도 있으며, 호출당한 함수가 할 수도 있습니다) C 방식은 인자 전달시 (순서가 어떻게 되는지는 잊어버렸는데) 호출한 함수에서 다시 인자를 꺼내서 제거하는 방식입니다. 어셈블리 코드로 보면

push argument1
push argument2 (1이 먼저인지 2가 먼저인지는 가물가물...)
call function
pop argument2
pop argument1 (물론 이보다 좀 효율적인 stack pointer를 직접 고치지만...)

보통은 이러한 __cdecl을 쓸 필요가 없는데, (C에서는 기본 전달 방식이니까) 문제는 C형식의 인자 전달방식을 사용하지 않는 라이브러리와 연결할 때 입니다. 가장 좋은 예가 M$사의 Windows의 API들입니다. Windows의 API들은 PASCAL 방식의 인자 전달 방식을 사용합니다. 역시 인자 전달 순서는 기억나지 않고, 호출당한 함수에서 stack의 인자를 제거합니다. 어셈블리어로 보면

procedure ()
....
pop argument2
pop argument1

push argument1
push argument2
call procedure

Windows의 API가 이렇게 구성된 이유는 여러가지가 있겠지만, 그 중 한가지는 x86 시스템에서 PASCAL 방식의 인자 전달방식이 더 효율적이기 때문입니다. ret 어셈블리 명령에서 직접 stack pointer를 조정할 수 있기 때문이죠. ret 8 하면 함수에서 돌아감과 동식에 stack pointer를 8만큼 조정하게 됩니다.

이렇게 한가지 이상의 방식으로 함수를 호출할 수 있으므로, 해당 함수가 어떠한 방식으로 사용되는지에 대해 정의할 필요가 있습니다. 이것이 __cdecl의 역할이 되겠습니다. Windows 함수들을 잘 살펴보시면 (include 디렉토리안의 헤더파일들) __cdecl 대신 PASCAL로 선언되어 있는 함수를 찾으실 수 있을 것입니다.

물론 UNIX의 경우 시스템 함수들이 C로 구현되어 있기 때문에 이러한 경우가 거의 없습니다. (파스칼로 만들어진 함수들과 연동하기 위해서는 필요하겠죠)
728x90

'Research > Programming' 카테고리의 다른 글

#, ##  (0) 2002.12.04
C Bit Fields  (0) 2002.12.04
register와 volatile 키워드의 역할  (0) 2002.12.04
volatile  (0) 2002.12.04
What Is Alignment  (0) 2002.12.04