호출 규약

Jaemyeong Lee·2024년 8월 9일
0

FastCampusC++

목록 보기
46/78

C++ 호출 규약(Call Convention) 분석

호출 규약(Call Convention)은 함수가 호출될 때 함수의 인수들이 어떻게 전달되고, 함수가 실행된 후 결과가 어떻게 반환되는지를 정의하는 규칙입니다. 호출 규약은 함수와 호출자 간의 약속으로, 다양한 컴파일러나 시스템에서 일관성 있게 함수를 호출하고 결과를 얻기 위해 필수적인 개념입니다. 이번 블로그 포스트에서는 PDF 자료를 바탕으로 호출 규약에 대해 자세히 분석해 보겠습니다.

1. 호출 규약의 기본 개념

호출 규약은 함수 호출 시 스택에 인수들이 어떻게 저장되는지, 레지스터가 어떻게 사용되는지, 그리고 함수가 끝난 후 반환 값이 어떻게 전달되는지를 정의합니다. 호출 규약은 프로세서 아키텍처와 운영체제에 따라 다를 수 있으며, 주요 호출 규약으로는 cdecl, stdcall, fastcall 등이 있습니다.

2. 호출 규약에서 스택과 레지스터의 역할

함수가 호출될 때, 인수들은 스택에 푸시(push)되거나 특정 레지스터에 저장됩니다. 이 과정은 호출 규약에 따라 다릅니다. 예를 들어, x86 아키텍처에서 cdecl 호출 규약은 인수들이 스택에 푸시되고, EAX 레지스터가 반환 값을 저장하는 데 사용됩니다.

PDF 자료에 따르면, 함수가 호출될 때 스택 프레임(stack frame)이 설정되고, ESP(Stack Pointer)와 EBP(Base Pointer) 레지스터가 함수 내에서 지역 변수와 인수를 관리하는 데 사용됩니다. 반환 주소는 EIP(Instruction Pointer)에 저장되며, 함수가 끝나면 이 주소로 돌아가 프로그램이 계속 실행됩니다.

3. C++에서 호출 규약의 예제 분석

PDF에서 제공된 예제 코드와 스택 상태를 통해, 호출 규약이 실제로 어떻게 적용되는지 살펴보겠습니다.

int sum(int x, int y)
{
    int total = x + y;
    return total;
}

int result = sum(10, 20);

이 코드에서 sum 함수가 호출되면 다음과 같은 과정이 발생합니다:

  1. 스택에 인수 저장: 먼저, 인수 1020이 스택에 푸시됩니다. 이때 10x에, 20y에 할당됩니다.
  2. EIP에 반환 주소 저장: 함수가 끝난 후 다시 돌아올 위치인 반환 주소가 스택에 저장됩니다.
  3. EBP 설정: 현재 스택 프레임의 시작을 나타내는 EBP가 설정됩니다.
  4. 함수 실행: xy를 더하여 total에 저장합니다.
  5. 반환 값 전달: 반환 값인 totalEAX 레지스터를 통해 호출자에게 전달됩니다.
  6. 스택 정리: 함수가 종료되면 스택 프레임이 정리되고, 스택 포인터가 호출 전에 있던 위치로 되돌아갑니다.

4. 다양한 호출 규약의 차이점

각 호출 규약은 스택과 레지스터를 다르게 사용합니다. 주요 호출 규약의 차이점을 정리하면 다음과 같습니다:

  • cdecl: 인수는 오른쪽에서 왼쪽 순서로 스택에 푸시됩니다. 호출자가 스택을 정리하며, 반환 값은 EAX 레지스터에 저장됩니다.
  • stdcall: cdecl과 비슷하지만, 호출된 함수가 스택을 정리합니다. 주로 윈도우 API에서 사용됩니다.
  • fastcall: 인수 중 일부는 레지스터에 전달되어 호출 속도를 높입니다. 나머지 인수는 스택에 저장됩니다.

5. 호출 규약의 중요성

호출 규약은 함수 간 일관된 통신을 보장하고, 특히 외부 라이브러리나 시스템 콜을 사용할 때 중요한 역할을 합니다. 잘못된 호출 규약을 사용할 경우, 스택이 불안정해지거나 잘못된 반환 값을 받을 수 있습니다.

6. 마무리

호출 규약은 함수 호출의 기초를 이해하는 데 필수적인 개념입니다. 이를 이해하면, 다양한 플랫폼에서의 함수 호출이 어떻게 이루어지는지, 그리고 어떻게 최적화할 수 있는지를 알 수 있습니다. 이번 포스트를 통해 호출 규약의 기본 개념과 다양한 유형을 이해하는 데 도움이 되었길 바랍니다.

profile
李家네_공부방

0개의 댓글