32비트에서는
stdcall, fastcall, cdecl 등의 호출규약이 존재하는데,
64Bit환경(EM64T) 에서는 이런것들이 전부 사라지고 단 하나의 호출규약만을 지원한다.
호출규약때문에 생기는 문제로 더이상 고민하지 않아도 된다.
일명 x64 call 이라고 하는방식인데
델파이와 C++빌더에서 많이 사용하는 FastCall 의 확장이라고 할 수 있겠다.
fastcall 은 처음 2개의 인수를 ECX와 EDX를 통해서 넘기는데, 64Bit 에서는 총 8개까지의 파라메터를 레지스터를 통해서 넘긴다.
정수인자(64bit)가 넘어오면, 각각 RCX,RDX,R8,R9 레지스터를 통해서 넘긴다.
여기서 RCX와 RDX는 각각 ECX, EDX가 64비트로 확장된 레지스터이며, R8 R9는 64Bit 에서 추가된 범용 레지스터이다. R8~R15 까지의 레지스터가 추가되었다.
두번째로 부동소수점(128bit) 인자가 넘어오면, XMM0~XMM3 까지의 레지스터를 사용해서 넘긴다.
XMM0~XMM3은 Streaming SIMD Extensions 즉 인텔의 SSE기술에서 사용하는 레지스터로 XMM0~XMM7까지의 8개가 존재하였다. 하지만 64Bit 로 넘어오면서 이도 확장되어 XMM0~15까지 총 16개의 레지스터가 존재한다.
리턴값은 정수형의 경우에는 32Bit(EAX)와 마찬가지로 RAX를 통해서 반환하며, 부동소수점은, XMM0을 통해서 반환한다.
그리고 마지막으로 스택정리가 남았는데... 스택을 cdecl 과 마찬가지로 호출 한 측에서 정리한다.
한가지 호출규약으로 가변인자를 지원하려다보니 이런 상황이 된 것 같다.
호출규약으로 인한 여러 문제점을 해결하는 대신, 함수호출하기 위한 코드가 길어지는 오버헤드가 생기고 말았다. 포인터가 64비트로 확장한것에 겸해서 이래저래 64Bit 용 프로그램은 32Bit 용 프로그램보단 크기가 커지게 생겻다.
뭐 지금 당장이야 이렇긴 한데... 나중엔 어떻게될지 아무도 모른다.
범용 레지스터가 2배로 늘어낫으니 더 활용할 방법을 함수호출규약에서 찾을지도 모르고 어느 회사에선가 64비트에서 새로운 확장 함수호출규약을 만들어낼 지도 모른다 ㅡ.ㅡ
|