https://basaeng.tistory.com/50
함수 호출 시 일어나는 일
개요함수 호출 시에 어떤 일들이 일어나는지를 알면, 코드 해석과 디버깅에 큰 도움이될 것이다.간단한 개념을 알아보자. 예시와 설명은 x86아키텍처 기준이다. 함수의 형태 () { // 함수 본문 //
basaeng.tistory.com
일반적으로 함수에는 호출 규약이 존재합니다.
함수에서 사용되는 파라미터를 전달하기 위해 프로그램은 스택에 데이터를 쌓으며, 함수를 반환할 때는 이를 정리합니다.
x64에 오면서는 규약이 통일되었지만 x86에서는 서로다른 호출규약을 사용했습니다.
예를 들어 int Add(int a, int b)와 같은 함수가 있다면 a와 b가 파라미터이고, a와 b에 대해 스택에 push해 이를 사용하게 됩니다.
다만 이를 a, b순서로 넣을지 b, a순서로 넣을지의 차이와 스택을 어느 곳에서 정리할지에 대한 차이가 존재합니다.
일단 cdecl에 대해 알아보겠습니다.
cdecl
cdecl은 파라미터가 오른쪽에서 왼쪽으로 전달됩니다.
기본적인 C프로그램에서 사용되는 규칙으로 컴파일러는 아래와 같이 명령어를 만듭니다.
int c = Add_(2, 5);
0050103F 6A 05 push 5
00501041 6A 02 push 2
00501043 E8 B8 FF FF FF call Add_ (0501000h)
또한 중요한 것은 스택 정리를 호출자 측에서 한다는 것입니다.
00501048 83 C4 08 add esp,8
0050104B 89 45 F8 mov dword ptr [c],eax
함수에서 ret를 통해 원래의 실행흐름으로 돌아오면 esp에 파라미터가 사용한 크기를 더해 esp를 원상복구시킵니다.
push했을 때 감소했던 스택 포인터를 복구하는 것입니다.
stdcall
stdcall또한 파라미터가 오른쪽에서 왼쪽으로 전달됩니다.
다만 차이점이 있다면 스택 정리를 피호출자인 함수 내부에서 진행한다는 것입니다.
int _stdcall Add_(int a, int b)
{
00C31000 55 push ebp
00C31001 8B EC mov ebp,esp
return a + b;
00C31003 8B 45 08 mov eax,dword ptr [ebp+8]
00C31006 03 45 0C add eax,dword ptr [ebp+0Ch]
}
00C31009 5D pop ebp
00C3100A C2 08 00 ret 8
ret 8이라는 명령어를 실행하면 eip를 복구하면서 esp도 증가하게 됩니다.
cdecl과 stdcall의 차이점
cdecl과 stdcall의 차이점은 위에서 보다시피 스택의 정리 주체가 다르다는 것입니다.
이를 통해 생기는 차이점이 있습니다.
1. cdecl은 가변인자 처리가 가능하지만, stdcall은 불가합니다.
예를 들어 int인자 n개를 받는다면 cdecl은 호출하는 곳에서 인자를 몇개 사용하는지 알 수 있기 때문에 어셈블리로 명령어를 만들 수 있습니다. 호출자에서 각각 add esp n을 실행하고 이 때 n은 가변인자에 따라 바뀔 것입니다.
다만 stdcall의 경우 함수 내부에서 스택을 정리하기 때문에 ret n이 고정되어있어 가변인자를 처리할 수 없습니다.
2. 고정인자의 경우 stdcall이 호출부의 코드 크기로 이득을 볼 수도 있습니다.
stdcall의 경우 ret n만 사용하면 되지만, cdecl은 호출자마다 add명령이 붙기 때문에 함수를 여러곳에서 많이 호출한다면 어셈블리 명령어 줄의 차이가 발생할 수 있습니다.
따라서 Windows에서 사용하는 WINAPI의 경우 _stdcall로 함수가 짜여져 있습니다.

fastcall
fastcall은 위의 규약들과 다르게 1, 2번째 인자를 레지스터에 넣습니다. (ecx, edx) 이후의 인자들은 그대로 스택에 넣습니다. 메모리 접근을 줄일 수 있기 때문에 fastcall이라는 이름을 가집니다.
레지스터를 사용하는 것이기 때문에 더 빠르지만 그만큼 함수 내부에서는 사용할 수 있는 레지스터에 제약이 생기게 됩니다.
레지스터 사용이 적거나 간단한 연산에는 도움이 될 수 있습니다.
다만 inline호출하는게 더 빠를 수는 있겠네요
thiscall
thiscall은 c++의 클래스 객체에 사용되는 호출규약입니다.
클래스 내부의 함수는 자신 객체의 포인터를 가져야 객체 내부 변수 등에 접근할 수 있습니다.
이를 위해 항상 this포인터를 함수 호출 시 ecx로 넘겨주는데 이를 thiscall이라고 부릅니다. (나머지 인자는 스택으로)

이후 x64에서는 통일되며(플랫폼에 따라서는 다를 수 있음)
많은 레지스터를 활용할 수 있게되어 레지스터를 적극적으로 활용하게 됩니다.
'CS > 프밍 잡지식' 카테고리의 다른 글
| 유니콘https와 VPN 뭐가 다를까? (0) | 2026.06.10 |
|---|---|
| [직렬화 버퍼] string 다루기 (0) | 2026.05.08 |
| Overlapped I/O 알아보기 - 2 (0) | 2025.12.09 |
| Overlapped I/O 알아보기 - 1 (0) | 2025.12.04 |
| 컴퓨터의 시간측정 응용 - FixedUpdate (1) | 2025.07.03 |