정의
x86 호출 규약은 인텔 x86 계열 프로세서에서 함수(또는 서브루틴)를 호출하고 반환할 때, 호출자와 피호출자 사이에 전달되는 인수, 반환값, 스택 정리 방식, 레지스터 사용 방법 등을 일관되게 정의한 규칙을 말한다. 이러한 규약은 프로그램 모듈 간, 혹은 서로 다른 컴파일러가 생성한 코드 간에 호환성을 확보하기 위해 마련된다.
개요
x86 아키텍처는 16비트 초기 모델(8086)부터 32비트(IA‑32) 및 64비트(x86‑64)까지 다양한 확장을 거쳐 왔으며, 각 확장 단계마다 여러 형태의 호출 규약이 존재한다. 주요 호출 규약은 다음과 같다.
| 규약 | 주 사용 환경 | 인수 전달 방식 | 반환값 | 스택 정리 책임 |
|---|---|---|---|---|
| cdecl | C 언어, GNU GCC, MSVC 등 | 인수를 오른쪽에서 왼쪽 순으로 스택에 푸시 | EAX(32‑bit) / RAX(64‑bit) | 호출자가 정리 |
| stdcall | Windows API, Win32 | 인수를 오른쪽에서 왼쪽 순으로 스택에 푸시 | EAX / RAX | 피호출자가 정리 |
| fastcall | 일부 MSVC, GCC 옵션 | 첫 1~2개의 인수를 레지스터(ECX, EDX)로 전달, 나머지는 스택 | EAX / RAX | 호출자가 정리(버전마다 다름) |
| thiscall | C++ 멤버 함수 (MSVC) | this 포인터를 ECX에 전달, 나머지는 cdecl 방식 | EAX / RAX | 호출자가 정리 |
| vectorcall | 고성능 수치 연산 (MSVC) | 첫 몇 개의 인수를 XMM/YMM 레지스터에 전달 | XMM0 등 | 호출자가 정리 |
| Microsoft x64 calling convention | 64비트 Windows | 첫 4개의 인수를 RCX, RDX, R8, R9 레지스터에 전달, 나머지는 스택 | RAX | 호출자가 정리 (스택은 16바이트 정렬) |
| System V AMD64 ABI | Linux, macOS 등 64비트 UNIX 계열 | 첫 6개의 인수를 RDI, RSI, RDX, RCX, R8, R9 레지스터에 전달, 나머지는 스택 | RAX | 호출자가 정리 (스택은 16바이트 정렬) |
각 규약은 스택 프레임 레이아웃, 레지스터 보존 규칙(callee‑saved vs. caller‑saved), 바이트 정렬(예: 16‑byte 정렬) 등을 상세히 정의한다. 규약에 따라 동일 바이너리 내에서도 함수가 서로 다른 방식을 사용하도록 할 수 있으며, 이는 컴파일러 옵션(-m32, -m64, -fcall-saved-reg, -masm=intel 등)이나 어셈블리 파일에 명시적인 디렉티브(.cdecl, .stdcall 등)로 지정한다.
어원/유래
- x86: 인텔 8086 프로세서(1978)에서 시작된 16비트 마이크로프로세서 제품군을 가리키는 명칭이며, 이후 80186, 80286, 80386, 80486 등으로 확장된 라인업을 포괄한다. “x86”이라는 표기는 8086, 80186 등에서 공통으로 나타나는 “86”이라는 숫자를 따온 것이다.
- 호출 규약: 한국어 표현으로 “calling convention”을 직역한 용어이며, “호출”(function call)과 “규약”(convention, agreement)을 결합한 형태이다.
특징
- 호환성 보장: 서로 다른 컴파일러가 생성한 객체 파일·라이브러리를 연결할 때 일관된 호출 규약을 사용하면 바이너리 호환성이 유지된다.
- 성능 최적화: 레지스터를 활용해 인수를 전달하는 규약(예: fastcall, vectorcall)은 메모리 접근을 최소화해 호출 오버헤드를 줄인다.
- 스택 정렬 요구: 대부분의 64비트 호출 규약은 스택을 16바이트 단위로 정렬하도록 요구한다. 이는 SIMD 명령어 사용 시 메모리 접근 오류를 방지한다.
- 레지스터 보존: 규약마다 호출자(caller)와 피호출자(callee) 중 어느 쪽이 특정 레지스터 값을 보존해야 하는지가 명시된다. 예를 들어, System V AMD64 ABI에서는 RBX, RBP, R12–R15 등을 callee‑saved 레지스터로 정의한다.
- 플랫폼 차이: 동일한 x86 아키텍처라도 운영체제와 ABI에 따라 기본 호출 규약이 다르다. Windows는 자체 규약을, Linux·macOS는 System V ABI를 따른다.
관련 항목
- x86 – 인텔 및 AMD가 설계한 32·64비트 호환 마이크로아키텍처.
- Calling convention – 함수 호출 시 인수 전달·스택 관리·레지스터 사용을 규정하는 국제적인 개념.
- ABI (Application Binary Interface) – 운영체제와 하드웨어 수준에서 정의된 바이너리 호환 규격, 호출 규약을 포함한다.
- Microsoft x64 calling convention – Windows 64비트 환경에서 정의된 호출 규약.
- System V AMD64 ABI – UNIX 계열 64비트 환경에서 널리 사용되는 호출 규약.
- cdecl, stdcall, fastcall – 각각 C 언어와 Windows API 등에서 전통적으로 사용된 호출 규약.
※ 본 문서는 2026년 현재까지 확인된 공신력 있는 자료(인텔 아키텍처 매뉴얼, Microsoft 문서, GNU GCC 매뉴얼 등)를 기반으로 작성되었다.