티스토리 뷰

텍스트 언어 호출 규약(함수를 호출 하는 방법에 대한 약속)


텍스트 언어에서 함수를 호출하는 방식(약속)을 텍스트 언어 호출 규약이라고 합니다. 함수를 호출하고, 어떻게 리턴하며 이에 대한 부분이 어디에 저장되고, 어떻게 지워지는지를 결정하는 규약입니다.


언어 호출 규약은 __cdecl,__stdcall,__fastcall, thiscall, naked 등이 있지만, 자주 사용되는 함수 호출 규약은 __cdecl, __stdcall이 있습니다. 


 키워드

 스택 정리

 매개 변수 전달

 __cdecl

 Caller

 스택에서 매개 변수를 반대 순서로(오른쪽에서 왼쪽으로) 푸시합니다.

 __clrcall

 n/a

 CLR 식 스택에서 매개 변수를 순서대로 로드합니다(왼쪽에서 오른쪽).

 __stdcall

 호출 수신자

 스택에서 매개 변수를 반대 순서로(오른쪽에서 왼쪽으로) 푸시합니다.

 __fastcall

 호출 수신자

 레지스터에 저장된 다음 스택에서 푸시됩니다.

 __thiscall

 호출 수신자

 스택으로 푸시됩니다. 이 포인터가 ECX에 저장 되었습니다

 __vectorcall

 호출 수신자

 레지스터에 저장된 다음, 스택에서 매개 변수를 반대 순서로(오른쪽에서
 왼쪽으로) 푸시합니다.


__cdecl과 __stdcall에 대해서 자세히 알아보고, 나머지는 기본 설명만 하고 넘어가도록 하겠습니다.


 

__cdecl 

__stdcall 

 인자 전달 순서

오른족에서 왼쪽으로 스택에 전달 

오른쪽에서 왼쪽으로 스택에 전달 

 스택 처리

호출측에서 스택 삭제

함수(호출당하는 쪽)가 스택 삭제

네이밍 규칙 

이름 앞에 _가 붙음 

이름 앞에 _가 붙음

이름뒤에는 @로 시작되는 10진수의 값이 명명됨 

 대소문자 변환

없음 

없음 



1) cdecl


__cdecl 은 C 및 C++ 프로그램의 기본 호출 규칙입니다. 스택은 호출자에 의해서 정리가 되고, 스택 클린업 코드를 포함하도록 호출하기 위해 __stdcall보다 큰 명령문을 생성합니다. ARM 및 x64 프로세서에서는 __cdecl이 컴파일러에서 수락 및 무시됩니다. 예는 아래와 같습니다.


// Example of the __cdecl keyword on function
int __cdecl system(const char *);
// Example of the __cdecl keyword on function pointer 

typedef BOOL (__cdecl *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, ...);



2) __stdcall


stdcal 호출 규약은 마이크로소프트 Win32 API 및 오픈 왓콤 C++의 표준 호출 규약입니다. 예는 아래와 같습니다. 


// Example of the __stdcall keyword
#define WINAPI __stdcall
// Example of the __stdcall keyword on function pointer 

typedef BOOL (__stdcall *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, ...);


이 두개의 가장 큰 차이점은 스택 정리 주체가 누구인가이지만, 실상 사용자 입장에서 별다른 차이가 없습니다. 컴파일 된 결과에 어떤것을 쓰던 별다른 차이가 없기 때문으로 보입니다. 또한 생성된 결과 사이즈도 별다른 차이가 없습니다. cdecl이 좀더 큰 결과물을 생성합니다.


하지만 __cdecl은 가변 인수를 받는 반면, __stdcall은 가변 변수를 받지않습니다. 그 이유는 stdcall이 함수가 직접 스택을 정리하기 때문에 가변인수에 대한 크기를 알수 없기 때문이죠. 호출하는 놈들 중에서 호출원이 스택을 정리하는 건 cdecl 밖에 없기 때문에, 가변 인자를 받을 수 있는 호출규약은 cdecl가 유일하다고 할 수 있습니다. 


이글이 도움이 되셨나요?

그렇다면 아래의 그림을 클릭해주세요.


댓글