Calling Conventions

호출 규칙은 OS 아키텍처에 따라 함수가 서로 인자를 전달하고 스택을 정렬하며, 레지스터를 보존하는 방식을 표준화한 규칙(ABI: Application Binary Interface)입니다.

x64

x64 ABI는 기본적으로 4개의 레지스터 빠른 호출 규칙을 사용합니다.

매개 변수 형식
첫번째 인자
두번째 인자
세번째 인자
네번째 인자

정수

rcx

rdx

r8

r9

부동 소수점

xmm0

xmm1

xmm2

xmm3

함수를 호출할 때 인자가 정수인지 부동 소수점인지에 따라 다른 레지스터에 저장되는데, 만약 두 종류가 섞인 채로 함수가 호출되면 다음 규칙대로 저장됩니다.

# 인자가 모두 정수
func1(int a, int b, int c, int d); // rcx = a, rdx = b, r8 = c, r9 = d

# 모두 부동 소수점
func3(float a, double b, float c, double d); // xmm0 = a, xmm1 = b, xmm2 = c, xmm3 = d

# 정수 및 부동 소수점 혼합
func3(int a, double b, int c, float d); // rcx = a, xmm1 = b, r8 = c, xmm3 = d

함수의 인자가 4개를 초과할 경우, 나머지 인자는 스택에 저장됩니다.

함수의 인자들을 레지스터에 저장하기 위해서는 함수의 호출 전에 공간을 미리 비워둬야 합니다. 인자가 4개 이하일 경우 예약된 레지스터 4개가 비워지며 5개 이상일 경우 스택에 저장되는데, 이때 생기는 공간을 섀도 저장소라고 합니다.

아래는 6개의 인자에 대해서 스택에 저장하는 방식을 어셈블리로 나타냈습니다.

함수가 호출된 직후에는 rsp에 반드시 리턴 주소(return address)가 저장됩니다.

References

Last updated