공부/Effective C++

항목 3 ] 함수 호출 규약

-=HaeJuK=- 2013. 6. 11. 15:38

C++ 함수 호출 규약 (calling conventions)은 함수 호출 시 함수 인자와 반환값을 처리하는 방식을 정의하는 규칙입니다. 호출 규약은 컴파일러와 링커가 일관되게 함수 호출을 처리하도록 합니다. 

Visual Studio 2010 호츌 규칙 설정


다음은 주요 호출 규약의 종류, 설명, 차이점, 예제 코드, 그리고 간단한 어셈블리 코드 예제입니다.

1. cdecl (C Declaration)

  • 설명: 기본 C 호출 규약으로, 인자는 오른쪽에서 왼쪽으로 스택에 푸시됩니다. 함수 호출자가 스택을 정리합니다.
  • 장점:
    • 유연성: 가변 인수 함수에서 사용 가능.
    • 호출 규약의 일관성: C와 C++에서 많이 사용되어 표준화됨.
    • 디버깅 편리성: 호출자가 스택을 정리해 디버깅이 쉬움.
int __cdecl add(int a, int b) {
    return a + b;
}

push ebp
mov ebp, esp
mov eax, [ebp+8]  ; a
add eax, [ebp+12] ; b
pop ebp
ret

2. stdcall (Standard Call)

  • 설명: Windows API에서 주로 사용됩니다. 인자는 오른쪽에서 왼쪽으로 스택에 푸시되며, 함수 자체가 스택을 정리합니다.
  • 장점:
    • 간결함: 함수가 스택을 정리해 호출 코드가 간결함.
    • WinAPI 적합성: 대부분의 Windows API 함수가 stdcall 사용.
    • 스택 사용의 일관성: 함수가 스택을 정리해 일관성 유지.
int __stdcall multiply(int a, int b) {
    return a * b;
}

push ebp
mov ebp, esp
mov eax, [ebp+8]  ; a
imul eax, [ebp+12] ; b
pop ebp
ret 8  ; Clean up stack (2 * 4 bytes)

 

3. fastcall

  • 설명: 인자를 레지스터로 전달하여 호출 오버헤드를 줄입니다. 첫 두 개의 인자가 ECX와 EDX 레지스터에 전달됩니다.
  • 장점:
    • 성능 향상: 레지스터를 사용해 함수 호출 오버헤드 감소.
    • 빠른 함수 호출: 레지스터를 사용해 인자를 전달, 스택 접근 시간 절약.
    • CPU 레지스터 활용: 연산 속도 향상.
int __fastcall subtract(int a, int b) {
    return a - b;
}

; Assume a is in ECX and b is in EDX
mov eax, ecx  ; a
sub eax, edx  ; a - b
ret

 

4. thiscall

  • 설명: C++ 멤버 함수 호출 규약으로, this 포인터가 ECX 레지스터에 전달됩니다. 나머지 인자는 cdecl 규약을 따릅니다.
  • 장점:
    • C++ 멤버 함수 최적화: 멤버 함수에서 this 포인터 전달 최적화.
    • 객체 지향 프로그래밍에 적합: 클래스 멤버 함수 호출에 특화.
    • 디버깅 편리성: this 포인터 위치를 쉽게 추적 가능.
class MyClass {
public:
    int __thiscall increment(int a) {
        return this->value + a;
    }
private:
    int value;
};


; Assume 'this' is in ECX, and a is on the stack
mov eax, [ecx]      ; Load 'this->value'
add eax, [esp+4]    ; Add a
ret

 

반응형