함수 호출 규약
함수 호출 규약
함수 호출 규약이란?
- 함수를 호출하는 방식에 대한 약속이다.
- 함수 호출 규약은
1. 인자 전달 방법 2. 인자 전달 순서 3. Stack Frame 정리 방법
이 세가지에 따라 종류를 구분한다.
주요 함수 호출 규약을 보기 전에 알아야 할 용어.
Caller(호출자) - 함수를 호출함.
Callee(피호출자) - 호출을 당하는 함수.
ex) main 함수에서 A함수를 호출했을 때, Caller는 main함수이고, Callee는 A함수이다.
함수 호출 규약은 크게 세 가지 방식이 있다.
① C/C++ 등의 컴파일러에서 사용하는 cdecl 방식.
② Win32 API 등에서 사용하는 stdcall 방식.
③ 컴파일러 업체에 따라 달리 사용하는 fastcall 방식.
자세히 보기.
① cdecl 방식.
- 호출자가 스택을 정리한다.
- 인자는 오른쪽에서 왼쪽 순으로 전달된다.
- 호출자가 피호출자를 호출 시에 전달되는 인자의 개수를 알고 있기 때문에 가변 인수 함수를 만들 수 있다는 장점이 있다.
- 함수를 호출할 때마다 인자정리 코드를 추가하기 때문에 코드가 길다.
- Parameter 리턴 값이 4byte 이하인 경우 - EAX 레지스터를 사용하고, 이상인 경우는 EDX:EAX 레지스터 쌍 사용.
이해를 돕기위한 예.
위 메인 함수를 어셈블리 한 결과:
② stdcall 방식.
- 피호출자가 스택을 정리한다.
- 인자는 오른쪽에서 왼쪽 순으로 전달된다.
- Win32 API에서는 가변 인수 함수가 없기 때문에, 매개변수의 개수가 고정적이다.
- Parameter 리턴 값이 4byte 이하인 경우 - EAX 레지스터를 사용하고, 이상인 경우는 EDX:EAX 레지스터 쌍 사용.
이해들 돕기위한 예.
위 메인 함수를 어셈블리 한 결과:
③ fastcall 방식.
- 처음 2개의 인자는 레지스터(ECX, EDX) 사용하고, 그 이후의 인자는 Stack Frame 사용.
- 인자는 오른쪽에서 왼쪽 순으로 전달된다.
- 피호출자가 스택을 정리하나 레지스터를 이용하므로 정리할 내용이 없어서 따로 정리를 하지 않음.
- Parameter 리턴 값이 4byte 이하인 경우 - EAX 레지스터를 사용하고, 이상인 경우는 EDX:EAX 레지스터 쌍 사용.
- 레지스터를 사용하기 때문에 다른 호출 규약에 비해 인수 전달 속도가 빠르다.
- C++에서는 호출 규약이 지원되지 않는다.
이해들 돕기위한 예.
위 메인 함수를 어셈블리 한 결과:
코드 출처: http://blog.eairship.kr/254