개발

호출 규약

호출 규약 (Calling Convention)

함수 호출 규약(Calling Convention)이란 호출자(Caller) 피호출자(Callee) 간에 함수를 호출하는 방식에 대한 약속이다. 함수 호출 규약은 인자 전달 방법, 인자 전달 순서, 스택 프레임 정리 방법에 따라 종류를 나눈다. 일반적으론 x64, x86 기준으로 호출 규약을 나눈다. window x64에서는 x64-call 사용하며 x86에서는 stdcall, cdecl, fastcall, thiscall 등을 사용한다. 다음은 x86 호출 규약 목록이다.

 

출처 : X86_호출_규약 위키

 

  • cdecl 방식

cdecl 방식은 C/C++ 에서 기본적으로 사용되는 호출 규약이다. 인자는 오른쪽에서 왼쪽으로 전달되며 호출자가 스택을 정리한다.

 

예를 들어 다음과 같은 함수를 보자.

int sum(int a, int b) 
{
 	return a + b;
} 

int main() 
{ 
	sum(10, 4); 
	return 0; 
}

 

메인 함수에서 인자 10 4 sum함수에 전달한다. sum 함수는 전달된 인자를 더하여 값을 반환한다. 이때 메인함수를 어셈블리어로 확인하면 다음과 같다.

 

cdecl 방식 어셈블리 코드

 

오른쪽에서 왼쪽으로 인자가 차례대로 스택에 올라가는 것을 있다. sum(10, 4)에서 인자는 4, 10 순서로 전달된다. sum 함수를 호출하고 나서 add esp, 8 호출자(메인 함수)에서 스택을 관리하는 것을 확인할 있다. push 4 push 0ah 인자가 전달되었음을 확인할 있다. 이와 같이, cdecl 방식은 호출자가 피호출자의 스택 프레임을 정리하는 것을 있다.

 

  • stdcall 방식

stdcall 방식은 Win32 API에서 사용된다. 인자는 오른쪽에서 왼쪽으로 전달되며 피호출자가 스택을 정리한다.

int __stdcall sum(int a, int b)
{
 	return a + b;
} 

int main() 
{ 
	sum(10, 4); 
	return 0; 
}

마찬가지로 어셈블리어로 확인하면 다음과 같다.

stdcall 방식 main 어셈블리 코드

오른쪽에서 왼쪽으로 인자가 전달된다. stdcall 방식은 피호출자에서 스택을 정리하기에 호출자에 스택을 관리하는 코드가 존재하지 않는다. 피호출자를 살펴보자.

stdcall 방식 sum 어셈블리 코드

마지막 부분을 보면 ret 8 sum 함수 내에서 스택을 정리하는 것을 확인할 있다. 반환이 끝난 ESP(스택 포인터) 8만큼 증가시킨다.

 

  • fastcall 방식

fastcall 방식은 스택이 아닌 가까운 레지스터를 사용함으로써 호출 속도가 빠르다. 

int __fastcall sum(int a, int b) 
{
 	return a + b;
} 

int main() 
{ 
	sum(10, 4); 
	return 0; 
}

fastcall 방식 main 어셈블리 코드

오른쪽에서 왼쪽으로 인자가 전달된다. cdecl, stdcall 방식과 다르게 edx, ecx 레지스터를 사용하여 인자를 전달한다.

 

fastcall 방식 sum 어셈블리 코드

edx 레지스터 값을 b 전달하고 ecx 레지스터 값을 a 전달한다. 값을 더하여 eax 레지스터로 전달한다. 만일 인자가 4개를 넘어가게되면 스택을 사용한다.

 

</div align="center">

호출 규약 

인자 전달 순서 인자 전달 매체 스택을 정리하는 함수
cdecl 오른쪽 스택 호출자(Caller)
stdcall 오른쪽 스택 피호출자(Callee)
fastcall  오른쪽 레지스터 + 스택 피호출자(Callee)

'개발' 카테고리의 다른 글

ulimit 명령어와 Select, Poll 함수  (0) 2020.10.12
The file couldn’t be opened because you don’t have permission to view it.  (0) 2020.10.07
PFX 인증서 생성  (0) 2020.06.19
BouncyCastle  (0) 2020.06.19
구조체 메모리 할당  (0) 2020.05.21