문서 편집 권한이 없습니다. 다음 이유를 확인해주세요: 요청한 명령은 다음 권한을 가진 사용자에게 제한됩니다: 사용자. 문서의 원본을 보거나 복사할 수 있습니다. '''System V ABI'''(System V Application Binary Interface)는 유닉스 계열 운영체제에서 실행 파일 형식, 데이터 타입 크기, 함수 호출 규약 등을 정의하는 규격이다. 현대의 64비트 UNIX 계열 (Linux, *BSD) 시스템에서는 주로 '''amd64(x86-64) System V ABI'''가 사용되기에 이 문서는 '''amd64(x86-64) System V ABI'''를 중심으로 설명한다. == amd64 System V ABI의 특징 == === 데이터 모델 (LP64) === amd64 System V ABI에서는 다음과 같은 LP64 데이터 모델을 사용한다. * <code>int</code> : 32비트 * <code>long</code>, <code>long long</code> : 64비트 * 포인터(<code>void *</code> 등) : 64비트 이는 C 코드에서 정수와 포인터 크기를 가정할 때 중요한 전제이다. === 함수 인자 전달 규칙 === 정수형, 포인터형 등 대부분의 스칼라 인자는 다음 순서의 레지스터로 전달된다. {| class="wikitable" ! 인자 번호 !! 사용 레지스터 |- | 1번째 인자 || RDI |- | 2번째 인자 || RSI |- | 3번째 인자 || RDX |- | 4번째 인자 || RCX |- | 5번째 인자 || R8 |- | 6번째 인자 || R9 |} * 7번째 인자부터는 스택에 8바이트 단위로 저장된 뒤 전달된다. * 부동소수점 인자(<code>float</code>, <code>double</code>)는 XMM0–XMM7 레지스터를 통해 전달되며, 정수 인자와는 별도로 순서가 관리된다. 스택은 함수 호출 시 16바이트 정렬(alignment)을 유지해야 하며, 컴파일러가 이를 맞추도록 코드를 생성한다. === 반환값 규칙 === * 대부분의 정수/포인터 반환값: RAX * 128비트까지의 일부 정수/구조체 반환: RAX와 RDX 조합 * 부동소수점 반환값: XMM0 더 큰 구조체 반환 등 특수한 경우에는 호출자가 반환 버퍼를 준비하고 포인터를 넘기는 방식 등이 사용된다. === 레지스터 보존 규약 === amd64 System V ABI는 어떤 레지스터를 누가 보존해야 하는지도 정의한다. * 호출자 저장(caller-saved): 함수 호출 시 덮어써져도 되므로, 필요한 경우 '''호출하는 쪽'''이 미리 저장해야 하는 레지스터 * 피호출자 저장(callee-saved): 함수가 종료될 때 원래 값이 유지되어야 하므로, '''호출되는 함수'''가 저장·복원해야 하는 레지스터 대표적인 규약은 다음과 같다. {| class="wikitable" ! 구분 !! 레지스터 |- | 호출자 저장 || RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, XMM0–XMM15 |- | 피호출자 저장 || RBX, RBP, R12, R13, R14, R15 |} RSP(스택 포인터)는 호출 전후에 일관되게 유지되어야 한다. == C 언어 예시 == 다음 예시는 정수 인자가 어떻게 레지스터와 스택으로 전달되는지 보여준다. <pre> int foo(int a, int b, int c, int d, int e, int f, int g); int caller(void) { return foo(1, 2, 3, 4, 5, 6, 7); } </pre> 위 호출에서 <code>foo</code>는 amd64 System V ABI에 따라 다음과 같이 인자를 받는다. * <code>a</code> → RDI (1번째 인자) * <code>b</code> → RSI (2번째 인자) * <code>c</code> → RDX (3번째 인자) * <code>d</code> → RCX (4번째 인자) * <code>e</code> → R8 (5번째 인자) * <code>f</code> → R9 (6번째 인자) * <code>g</code> → 스택 상의 슬롯 (7번째 인자) <code>foo</code>가 <code>int</code>를 반환하면, 그 값은 RAX에 담겨 <code>caller</code>로 전달된다. 부동소수점 인자의 경우: <pre> double add_double(double x, double y); double caller2(void) { return add_double(1.0, 2.0); } </pre> * <code>x</code> → XMM0 * <code>y</code> → XMM1 * 반환값(<code>double</code>) → XMM0 System V ABI 문서로 돌아갑니다.