CDECL 인수는 역순으로 스택에 푸시되고 호출자는 스택을 지우고 결과는 프로세서 레지스트리를 통해 반환됩니다 (나중에 "레지스터 A"라고 부릅니다). STDCALL에는 한 가지 차이점이 있습니다. 호출자는 스택을 지우지 않고 호출자가 수행합니다.
어느 것이 더 빠른지 묻습니다. 아무도. 가능한 한 기본 호출 규칙을 사용해야합니다. 특정 규칙을 사용해야하는 외부 라이브러리를 사용할 때 탈출구가없는 경우에만 규칙을 변경하십시오.
게다가 컴파일러가 기본값으로 선택할 수있는 다른 규칙이 있습니다. 즉, Visual C ++ 컴파일러는 프로세서 레지스터를 더 광범위하게 사용하기 때문에 이론적으로 더 빠른 FASTCALL을 사용합니다.
일반적으로 일부 외부 라이브러리에 전달 된 콜백 함수에 적절한 호출 규칙 서명을 제공해야합니다. 즉 qsort
, C 라이브러리에서 콜백 은 CDECL이어야합니다 (컴파일러가 기본적으로 다른 규칙을 사용하는 경우 콜백을 CDECL로 표시해야 함) 또는 다양한 WinAPI 콜백이 STDCALL (전체 WinAPI는 STDCALL 임).
다른 일반적인 경우는 일부 외부 함수에 대한 포인터를 저장할 때일 수 있습니다. 즉, WinAPI 함수에 대한 포인터를 만들려면 해당 유형 정의가 STDCALL로 표시되어야합니다.
다음은 컴파일러가 수행하는 방법을 보여주는 예입니다.
i = Function(x, y, z);
int Function(int a, int b, int c) { return a + b + c; }
CDECL :
push on the stack a copy of 'z', then a copy of 'y', then a copy of 'x'
call (jump to function body, after function is finished it will jump back here, the address where to jump back is in registers)
move contents of register A to 'i' variable
pop all from the stack that we have pushed (copy of x, y and z)
copy 'a' (from stack) to register A
copy 'b' (from stack) to register B
add A and B, store result in A
copy 'c' (from stack) to register B
add A and B, store result in A
jump back to caller code (a, b and c still on the stack, the result is in register A)
STDCALL :
push on the stack a copy of 'z', then a copy of 'y', then a copy of 'x'
call
move contents of register A to 'i' variable
pop 'a' from stack to register A
pop 'b' from stack to register B
add A and B, store result in A
pop 'c' from stack to register B
add A and B, store result in A
jump back to caller code (a, b and c are no more on the stack, result in register A)