함수의 호출 관례(function calling convention)란 함수의 파라미터를 스택에 푸시하는 순서, 푸시하는 쪽 및 이름 변화를 명시한 것이다.

 

변경자 푸시 순서 팝하는 쪽 이름 변화
__cdec 오른쪽에서 왼쪽으로 호출하는 쪽 prepended
__fastcall 왼쪽에서 오른쪽으로 호출당하는 쪽 @ prepended
__pascal 왼쪽에서 오른쪽으로 호출당하는 쪽 Uppercase
__stdcall 오른쪽에서 왼쪽으로 호출당하는 쪽 No change

푸시 순서

위쪽 표의 푸시 순서의 의미는 함수의 파라미터가 어느쪽에서부터 먼저 푸시를 하는지에 대한 말.

 

팝하느 쪽

팝하는 쪽의 의미는 함수 호출 후 종료 시점에서 함수의 스택을 정리할 때 스택의 팝을 어느쪽에서 하느냐에 대한 말이다.

 

이름 변화

- C방식의 경우 명칭 앞에 언더스코어 '_'가 붙는다.

- 레지스터 방식의 경우 @가 붙는다.

- Pascal 바익의 경우 모두 대문자로 바뀐다.

- win32 방식(__stdcall)의 경우 이름은 __stdcall이다.

 

windows의 api 함수는 모두 win32 방식을 이용한다.

모든 C++ 컴파일러에서 기본값은 cedecl이다. 

visual studio IDE에서 calling convention을 바꿀 수 있다.

 

visual c++에서 Windows 프로그래밍을 하더라도 기본 설정은 __cdecl이다.

windows 응용 프로그램의 시작 함수인 WinMain()은 __stdcall이지만 win32 콘솔 응용 프로그램의 시작 함수인 main()은 __cdecl이다.

 

#include <iostream>
using namespace std;

void __pascal f(int i, int j) {
	cout << i << " " << j << "\n";
}

void __cdecl g(int i, int j) {
	cout << i << " " << j << "\n";
}

int main() {
	int i, j;

	i = 1; j = 2;
	f(i == j, i = j);
	i = 1; j = 2;
	g(i == j, i = j);

	return 0;
}

__pascal일 경우 왼쪽에서 오른쪽으로 스택에 푸쉬되므로 "0 1"로 될 것이고

__cdecl일 경우 오른쪽에서 왼쪽으로 스택에 푸쉬되므로 "1 2"로 될 것이다.

 

visual studio ide로 이용 할 경우 컴파일 에러가 발생한다.

windows에서 더 이상 pascal 방식은 존재하지 않는다. 이것은 __stdcall로 대처되었다.

 

 

__fastcall로 바꿨다. 

#include <iostream>
using namespace std;

void __fastcall f(int i, int j) {
	cout << i << " " << j << "\n";
}

void __cdecl g(int i, int j) {
	cout << i << " " << j << "\n";
}

int main() {
	int i, j;

	i = 1; j = 2;
	f(i == j, i = j);
	i = 1; j = 2;
	g(i == j, i = j);

	return 0;
}

이 상태에서 실행을 하면 

__fastcall은 "0 2"이 나와야되고 

__cdecl은 "1 2"이 나와야 된다.

 

근데 막상 실행해보면 둘 다 "1 2"나 "0 2"가 나올 수 있다. 왜그럴까..

 

+ Recent posts