http://blog.naver.com/ljsk139/30143768284

 

함수호출규약(Calling Convention) 간단 정리

__cdecl (default 설정) 인자전달방법 : 스택에 저장하여 전달인자전달순서 : 오른쪽에서 왼쪽으로스택의 ...

blog.naver.com

 

__cdecl (default 설정)

 

  • 인자전달방법 : 스택에 저장하여 전달
  • 인자전달순서 : 오른쪽에서 왼쪽으로
  • 스택의 정리 : Caller에서 정리
  • 장점 : 가변인자를 사용할 수 있다.

 

__stdcall

 

  • 인자전달방법 : 스택에 저장하여 전달
  • 인자전달순서 : 오른쪽에서 왼쪽으로
  • 스택의 정리 : Callee에서 정리
  • 장점 : __cdecl보다 코드의 길이가 짧다. (좀 더 빠르다.)

 

 

__fastcall

 

  • 인자전달방법 : 처음 두개는 ECX, EDX를 이용, 나머지는 스택에 저장하여 전달
  • 인자전달순서 : 오른쪽에서 왼쪽으로
  • 스택의 정리 : Callee에서 정리
  • 장점 : 레지스터에 인자를 저장하기 때문에 속도가 더 빠르다.

 

Calling Convention에서의 중요한 것은 스택의 정리를 Caller에서 하느냐 Callee에서 하느냐이다.

 

 

  왼쪽의 그림의 경우는 Caller에 인자를 저장하는 형태이고 오른쪽 그림의 경우는 Callee에 인자를 저장하는 형태이다.

 

왼쪽의 그림에서 Callee가 스택을 정리한다고 생각을 해보자.

 

Callee는 인자가 자신의 스택영역에 있는 것이 아니기 때문에 인자의 개수가 몇개인지 체크를 해야하고, 그 이후에 정리를 해야한다. 그렇기에 절차가 복잡해 진다. 

 

하지만 Caller가 스택을 정리한다면 Callee를 호출하는 순간 인자의 개수를 이미 알고 있기 때문에, 스택을 정리하는 작업이 복잡하지 않다. 

 

그리고 또한 Caller에서 인자의 개수를 정해서 함수를 호출하는 것이기 때문에 인자의 개수는 변할 수가 있다. 그렇기에 __cdecl에서 가변인자함수를 지원하는 것이다.

 

반대로 오른쪽의 경우는 Caller보다 Callee가 스택을 정리하는 것이 유리하다. 하지만 이 경우는 가변인자함수를 지원할 수 없다. 

 

왜냐하면 스택의 정리 코드를 작성하려면 인자의 총 크기를 미리 알아야 하는데 가변인자함수의 경우는 인자의 개수가 가변적이므로 미리 예측할 수 없기 때문이다.

 

 

 

__cdecl과 __stdcall이 속도차이가 나는 이유는 정리 코드에서의 차이 때문이다.

 

__stdcall의 경우는 Callee가 작업을 마치고 스택을 정리할 때 

ret (인자의 총 크기)

로 정리를 한다.

 

__cdecl의 경우에는 Callee가 ret을 하고 나면 Caller가

add esp, (인자의 총 크기)

로 정리를 한다.

 

 

 

[정리]

 

 

 

 

https://ezbeat.tistory.com/425

'리버싱' 카테고리의 다른 글

RVA to RWA 쉽게 계산하기 [펌]  (0) 2022.04.27
EAT IAT 계산  (0) 2022.04.25
C#은 SecureSting 클래스  (0) 2021.07.09
.Net De'obfuscator 분석(진행 중)  (0) 2020.11.08
게임 해킹 띠오리(경로)  (0) 2020.11.02
블로그 이미지

wtdsoul

,