overview
c/c++ compiler는 여러 가지 호출 규약이 존재하는데 이러한 서로 다른 호출 규약들을 이해하는 것이 디버깅이나 어셈블리 언어로 만들어진 루틴들을 링크하는데 도움을 줄 수 있다.
이 글에서는 간단한 예제를 각각의 규약들에 따라서 어떻게 달라지는지를 도식화하여 보여줄 것이다.
calling convention
- void (one of calling convention) MyFunc( char c, short s, int i, double f );
- .
- .
- .
- void MyFunc( char c, short s, int i, double f )
- {
- .
- .
- .
- }
- .
- .
- .
- MyFunc('x', 12, 8192, 2.7183);
__cdecl

- 이 호출 방식을 사용했을 때 함수의 mangling된 이름은 _MyFunc이다.
- 스택 지우기는 caller(호출자)가 수행한다.
- 매개변수들은 오른쪽에서 왼쪽순으로 스택에 쌓인다.
__stdcall
- 이 호출 방식을 사용했을 때 함수의 mangling된 이름은 _MyFunc@20이다(C언어일 경우에).
- 스택 지우기는 callee(피호출자)가 수행한다.
- 매개변수들은 오른쪽에서 왼쪽순으로 스택에 쌓인다.
__thiscall
- 이 호출 방식을 사용했을 때 함수의 mangling된 이름은 임의적이다(함수의 다형성).
- 스택 지우기는 callee(피호출자)가 수행한다.
- 클래스 this 포인터가 ECX에 저장되고 매개변수들은 오른쪽에서 왼쪽순으로 스택에 쌓인다.
__fastcall
- 이 호출 방식을 사용했을 때 함수의 mangling된 이름은 _MyFunc@20이다(C언어일 경우에).
- __fastcall은 호출된 함수가 stack을 비우는 책임을 가진다.
- 좀더 빠른 매개변수 전달을 위해서 두개의 레지스터(ECX,EDX)를 사용하고 나머지 매개변수들은 오른쪽에서 왼쪽순으로 스택에 쌓인다.
Caller or Callee Stack Cleanup
C/C++ 언어가 기본적인 규약으로 정한 __cdecl이 가변인자를 지원하기 때문에 stack을 지우는 책임이 caller냐 callee냐 이렇게 두가지 경우로 나뉘게 되었다.
__stdcall은 고정된 인자의 크기에서 사용되는데, 인자의 크기가 고정되어 사용되므로 함수 자신은 스택의 크기를 언제나 알 수 있으므로 스택 해제를 RET와 ADD의 두 과정을 거치는 것이 아니라 RET argsize 단 한번의 명령으로 처리가 가능하므로 속도면에서 이득이 있다.
가변인자의 경우는 callee가 스택의 크기를 알 수 없으므로 __stdcall로는 스택을 지울 수 없다.
caller가 함수 호출후에 스택을 지우는 역활을 대신하고 callee는 스택에 대해서 신경쓰지말라는 규약이 바로 __cdecl인 것이다.
C or C++ Naming Mangling
함수 이름은 실제적으로 Mangling 규칙에 따라서 심볼화되어 함수 테이블에 저장된다. C언어의 경우에 호출 규약에 따라서 단순한 Mangling 규칙을 가지지만 C++언어는 함수의 다형성을 제공하기 때문에 C언어처럼 단순한 Mangling 규칙을 따르진 않는다.
C++언어의 Mangling 규칙은 컴파일러 제작사들에 따라서 약간씩 다르다. C++에서 특정 함수를 어떤 방식으로 mangling 할지를 결정할 수 있는데 그러한 선언문이 바로 extern string-literal 이다.
여기서 string-literal에는 "C", "C++"가 존재한다(MSVC경우). 만약 C언어로 작성된 오브젝트 파일에 함수를 C++ 언어로 작성한 프로그램에서 사용할 때 그 함수의 헤더파일을 포함해서 컴파일한다면 둘의 mangling이 달라서 같은 함수 이름을 다른 심볼로 가지므로 인해서 link error가 발생할 것이다.
이럴 경우를 대비하기 위해서 위와 같은 선언문이 존재한다. 실제로 표준 C라이브러리 함수들의 헤더파일을 보면 다 extern "C" 선언문이 붙어있는 것을 볼 수 있다.
trackback from: Xcode에서 Hello world만들기
답글삭제오늘은 어제 배운 Hello world프로그램을 만들어볼까 합니다. XCODE에선 처음 프로젝트를 열었을때 기본적으로 Hello world프로그램이 만들어져있지만 오늘은 지우고 만들어 보겠습니다. ▲Xcode의 첫 화면입니다. Create a new Xcode project를 클릭합니다. ▲ Create버튼을 클릭하면 이런창이 뜹니다. 이곳에서 C를 클릭합니다. ▲저장하실 위치를 선택후 ▲이런 창이 뜨면 준비가 끝난것 입니다. ▲대부분 c언어는 알고..