함수가 호출되고 반환되는 일련의 과정에서 정형화된 부분을 의미
- 함수 호출 시 매개변수의 전달을 어떻게 할 것인지
- 함수의 반환값은 어디에 저장해서 전달할 것인지 (eax)
- 함수 반환 이유 남은 스택의 정리를 어떻게 할 것인지? (전달된 매개변수의 정리를 호출자? 피호출자? 누가 할 것인가?
class MyClass
{
public:
// void Go(int a) {m_iV = a;}
void Go(int a, ...) { m_iV = a; }
int m_iV;
};
int main()
{
MyClass myClass;
myClass.m_iV = 3;
myClass.Go(5);
}
가변 인자 존재 x

가변 인자 존재 o

int Sum(int a, int b,...)
{
return a + b;
}
int main()
{
int c = Sum(3, 4);
}

함수 종료 후 main에서 add esp 8 을 통해 stack pointer를 내려주는 것을 확인.
int __stdcall Sum(int a, int b)
{
return a + b;
}
int main()
{
int c = Sum(3, 4);
}

함수 종료 시 Sum 함수 내부에서 ret 8 을 통해 stack pointer를 내려주는 것을 확인.
매개변수의 전달 순서 (오른쪽 -> 왼쪽 push)
정수의 경우, 기본적으로 2개의 매개변수는 레지스터를 통해 전달.
부동 소수점의 경우 무조건 push
스택 정리 주체
int __fastcall Sum(int a, int b)
{
return a + b;
}
int __fastcall Sum(int a, int b, int c)
{
return a + b + c;
}
LONGLONG __fastcall Sum64(LONGLONG a)
{
return a+3;
}
LONGLONG __fastcall Sum64(LONGLONG a, LONGLONG b)
{
return a + b;
}
double __fastcall Sum(double a, double b)
{
return a + b;
}
double __fastcall Sum(double a, double b, double c)
{
return a + b + c;
}
int main()
{
int fastcall1 = Sum(1, 2);
int fastcall2 = Sum(1, 2, 3);
double fastcall3 = Sum(1.0, 2.0);
double fastcall4 = Sum(1.0, 2.0, 3.0);
LONGLONG fastcall5 = Sum64(0x1111111122222222);
LONGLONG fastcall6 = Sum64(0x1111111122222222,0x2222222233333333);
}
정수 (4바이트)

Sum(a,b)의 경우는 ecx, edx 레지스터에 담겨서 전달되고, push하지 않기때문에 바로 ret
Sum(a, b, c)의 경우 인자가 3개이기 때문에 2개는 레지스터에, 한 개는 push한 후 호출된 함수에서 스택을 정리하는 것을 확인.
부동소수점 (float - 4 / double - 8)

매개변수의 개수와 상관없이 바로 스택에 푸쉬한 후, 호출된 함수에서 스택을 정리하는 것을 확인. 한 가지 특이한 것은 정수와는 다르게 값을 바로 push하지 않고 레지스터에 담은 후 그 값을 push하는 것을 볼 수 있다. 내 생각엔 아마 부동 소수점 데이터를 바로 못 담아서 레지스터를 활용하는 것 같은데.. 이것도 나중에 봤을 때 기억나도록 적어놓도록 한다..
8바이트
다음과 같은 형태로 push된다.

호출 규약이 통합됨 ( 호출 규약 명시해도 무시됨 )
매개변수의 전달 순서 (오른쪽 -> 왼쪽 push)
스택 정리의 주체 (호출자, Caller)
정수의 경우 rcx / rdx / r8 / r9 레지스터를 통해 전달
부동소수점의 경우 xmm0 / xmm1 / xmm2 / xmm3 레지스터를 통해 전달
클래스의 멤버 함수 호출 시 rcx를 통해 this 포인터 전달
값의 리턴은 rax (정수) / xmm0 (부동소수점) 레지스터를 활용
x86 호출 규약과 비교했을 때
매개변수가 레지스터만으로 부족한 경우는 매개변수를 저장할 공간을 늘리고, 기본적인 동작은 위와 비슷하다.
int Plus(int a, int b)
{
return a + b;
}
int main()
{
int a = Plus(1, 2);
}
기본적인 형태는 다음과 같다.

각 단계 직후의 상황을 a,b,c,d,e,f 로 표현했으며 그 순간의 스레드 스택은 이와 같다.






