이 영역을 누르면 첫 페이지로 이동
웬디의 기묘한 이야기 블로그의 첫 페이지로 이동

웬디의 기묘한 이야기

페이지 맨 위로 올라가기

웬디의 기묘한 이야기

C/C++ Windows Hooking 개발자의 블로그 입니다! 이곳은 개발 외에도 저의 취미들이 공유되는 기묘한 이야기가 펼쳐집니다.

__cdecl, __stdcall, __fastcall x86 호출 규약(Calling Convention)

  • 2016.01.01 20:02
  • ⌨ DEVELOPMENT/C++
반응형

Calling Convention

X86에선 호출 규약이 __cdecl, __stacll, __fastcall 등으로 나누어있지만 x64에선 __fastcall 하나의 호출 규약만을 사용하도록 정의 되어있습니다. (__fastcall은 x86 전용이라고 합니다. x64는 추후 다시 정리하겠습니다!)

오늘은 x86 호출 규약에 대해서만 정리를 해보겠습니다.


함수 호출규약을 아무것도 입력하지 않으면 기본값은 __cdecl 입니다.

해당 테스트는 Visual Studio 2015 Community 에서 이루어졌습니다.


__cdecl (c declaration)

이 규약에서 호출자는 스택에서 인수를 정리하며, printf() 와 같은 가변 인자 함수를 지원합니다.

함수의 호출시 함수 호출 전과 함수가 끝난 후의 ESP의 위치는 같아야 합니다. 그렇기때문에 함수를 사용하기 위해 사용한 스택을 누군가는 정리를 해주어야 한다는 것 입니다. 누군가는 caller 혹은 callee 가 되겠네요. (직접 하는일은 아니고 내부적으로 처리됩니다.)


__cdecl sample code


int cdecl_test1(int a, int b, int c) {
    int result = a + b + c;
    return result;
}

int __cdecl cdecl_test2(int a, int b, int c) {
    int result = a + b + c;
    return result;
}

int main()
{
    cdecl_test1(1, 2, 3);
    cdecl_test2(1, 2, 3);
    return 0;
}


__cdecl sample asm code


cdecl_test1(1, 2, 3);
00E53C3E  push        3  
00E53C40  push        2  
00E53C42  push        1  
00E53C44  call        cdecl_test1 (0E5134Dh)  
00E53C49  add         esp,0Ch  

     cdecl_test2(1, 2, 3);
00E53C4C  push        3  
00E53C4E  push        2  
00E53C50  push        1  
00E53C52  call        cdecl_test2 (0E51352h)  
00E53C57  add         esp,0Ch

2개의 asm 코드가 일치합니다.

위의 코드는 호출 규약을 입력하지 않은 코드이고

아래 코드는 __cdecl을 입력한 코드 입니다.

위에서 설명드린 대로 아무것도 입력하지 않으면 __cdecl이네요


asm code를 보게되면 push 3, push 2, push 1 을 하고있습니다.

즉, 오른쪽부터 왼쪽으로 인자를 스택에 넣고 있는 것 입니다.

그리고나서 call cdecl_test 함수를 호출하네요

그런데 다음줄에 add esp, 0Ch는 뭘까요??

함수 내부에서가 아닌 함수 외부에서 stack이 정리되고 있습니다. Caller에서 정리를 한다는 이야기가 되는것이죠


정리

- 전달 인자는 오른쪽에서 왼쪽으로 전달 된다.

- cdecl 방식은 caller 에서 전달 인자에 대한 Stack을 정리한다. (함수 외부)

- 호출 규약을 입력하지 않으면 기본값은 cdecl 이다


__stdcall

Win32 API 등의 표준 규약입니다.

Cdecl 방식과는 거의 비슷하게 동작하며, 어떤부분이 다르게 동작하는지 한번 봐보겠습니다.


__stdcall sample code


int __stdcall stdcall_test(int a, int b, int c) {
    int result = a + b + c;
    return result;
}

int main()
{
    stdcall_test(1, 2, 3);
    return 0;
}


__stdcall sample asm code


stdcall_test(1, 2, 3);
00E53C5A  push        3  
00E53C5C  push        2  
00E53C5E  push        1  
00E53C60  call        stdcall_test (0E51357h)

같은듯 다른 무언가가 있네요

스택에 전달인자를 넣는건 똑같고 함수 call 하는것까진 똑같네요

하지만 call 이후에 뭔가가 없습니다.

add esp,0Ch 의 부분이 여기엔 없네요

그것이 __cdecl과 __stdcall의 차이점 입니다.

바로 __cdecl은 caller가 stack을 정리하고 __stdcall은 callee가 직접 정리를 한다는것이죠


정리

- 전달 인자는 오른쪽에서 왼쪽으로 전달 된다.

- stdcall 방식은 callee 에서 전달 인자에 대한 Stack을 정리한다. (함수 내부)


__fastcall

이름부터 속도가 빠를 것 같은 호출 규약 입니다.

해당 규약은 표준화된 규약은 아니기때문에 컴파일러마다 다르게 처리됩니다.

일반적인 fastcall 호출 규약은 레지스터 내 하나 이상의 인수르 통과시키며 호출에 필요한 메모리 접근의 수를 줄입니다.

VisualStudio, GCC의 fastcall 은 처음 두 개의 인수(왼쪽에서 오른쪽)를 통과시켜 ECX, EDX에 맞추고 나머지 인수들은 오른쪽에서 왼쪽 순으로 스택으로 PUSH 하게 됩니다.


__fastcall sample code


int __fastcall fastcall_test(int a, int b, int c) {
    int result = a + b + c;
    return result;
}

int __fastcall fastcall_test2(int a, int b, int c, int d, int e) {
    int result = a + b + c + d + e;
    return result;
}

int main()
{
    fastcall_test(1, 2, 3);
    fastcall_test2(1, 2, 3, 4, 5);
    return 0;
}


__fastcall sample asm code


fastcall_test(1, 2, 3);
00E53C65  push        3  
00E53C67  mov         edx,2  
00E53C6C  mov         ecx,1  
00E53C71  call        fastcall_test (0E5135Ch)

    fastcall_test2(1, 2, 3, 4, 5);
00E53C76  push        5  
00E53C78  push        4  
00E53C7A  push        3  
00E53C7C  mov         edx,2  
00E53C81  mov         ecx,1  
00E53C86  call        fastcall_test2 (0E51361h)

여기서 fastcall이 왜 빠른지 나옵니다.

모든 전달 인자를 스택에 쌓는게 아니라 레지스터에 직접 넣어버림으로 인해서 속도를 향상시킨 방식입니다.


실제로 전달인자를 우측에서 좌측으로 입력하고,

처음 두개의 인자는 ECX, EDX 레지스터에 입력하는 모습을 볼 수 있습니다.

더불어 call 이후엔 스택을 정리하지 않는것으로 보아 이건 callee 즉 함수 내부에서 스택이 정리된다는것을 확인할 수 있습니다.


정리

- 전달 인자는 처음 두개는 ECX, EDX 레지스터에 직접 넣고 나머지에 대해선 오른쪽에서 왼쪽으로 전달 된다.

- fastcall은 레지스터를 직접 이용하기때문에 속도가 빠르다.

- fastcall 방식은 callee 에서 전달 인자에 대한 Stack을 정리한다. (함수 내부)

Disassembly는 지난번 소개해드렸던 방법으로 확인 및 테스트가 가능합니다.

2015/12/31 - [Development/Debugging] - visual studio 디버깅시 디스어셈블리 확인하기


반응형
저작자표시 비영리 동일조건 (새창열림)

'⌨ DEVELOPMENT > C++' 카테고리의 다른 글

[C/C++] convert string, wstring, utf-8  (9) 2019.07.06
[C/C++] 작업표시줄 아이콘 깜빡이게 하기 (FlashWIndow)  (0) 2019.07.03
[C++] std::string to std::wstring 서로 변환하기  (3) 2016.01.31
[C/C++] DLL injection. 다른 Process에 내 DLL Load 하기  (5) 2016.01.03
[C/C++] FormatMessage 윈도우 GetLastError를 메시지로!!  (0) 2015.12.29
[C/C++] IPC - Pipe client simple example  (0) 2015.12.28
[C/C++] IPC - Pipe server simple example  (1) 2015.12.21
[C/C++] string replace all 문자열 모두 치환  (0) 2015.12.11

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [C++] std::string to std::wstring 서로 변환하기

    [C++] std::string to std::wstring 서로 변환하기

    2016.01.31
  • [C/C++] DLL injection. 다른 Process에 내 DLL Load 하기

    [C/C++] DLL injection. 다른 Process에 내 DLL Load 하기

    2016.01.03
  • [C/C++] FormatMessage 윈도우 GetLastError를 메시지로!!

    [C/C++] FormatMessage 윈도우 GetLastError를 메시지로!!

    2015.12.29
  • [C/C++] IPC - Pipe client simple example

    [C/C++] IPC - Pipe client simple example

    2015.12.28
다른 글 더 둘러보기

정보

웬디의 기묘한 이야기 블로그의 첫 페이지로 이동

웬디의 기묘한 이야기

  • 웬디의 기묘한 이야기의 첫 페이지로 이동

검색

메뉴

  • 홈
  • 태그
  • 방명록
  • 이야기

카테고리

  • 분류 전체보기 (204)
    • MY STORY (2)
    • 📸 WALKING WITH YOU (85)
      • 아이슬란드 신혼여행 이야기 (14)
      • 대한민국 구석구석 (62)
      • CONTAX N1 + T* 28-80mm (4)
      • SAMSUNG NX3000 (1)
      • 어느 멋진 날 (4)
    • ⌨ DEVELOPMENT (80)
      • BOOK:Review (1)
      • AI (13)
      • C++ (26)
      • Python (10)
      • WIndows Hooking (9)
      • Windows Kernel (3)
      • Design Pattern (3)
      • Debugging (9)
      • Tools (0)
      • Project (1)
      • Android (1)
      • 상업용 무료폰트 (4)
    • OS (4)
      • News (0)
      • Windows 일반 (4)
    • 모바일 (2)
      • 모바일 게임 (2)
    • 멘사 퍼즐 (9)
    • 생활 꿀 TIP (7)
      • 건강 (3)
      • 일상 (2)
    • 물생활 (8)
      • 골든볼 라미네지 롱핀 (8)
    • IT 기기 (2)
    • BLOG (4)
      • TISTORY BLOG TIP (3)

최근 글

인기 글

댓글

공지사항

아카이브

태그

  • 아이슬란드
  • AI
  • windbg
  • c++
  • c
  • 신혼여행
  • 해외여행
  • 카페

나의 외부 링크

  • kernel undocument api
  • 지구 관찰자의 일기
  • 지구와 지구곰

정보

WENDYS의 웬디의 기묘한 이야기

웬디의 기묘한 이야기

WENDYS

블로그 구독하기

  • 구독하기
  • RSS 피드

방문자

  • 전체 방문자
  • 오늘
  • 어제

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. © WENDYS. Designed by Fraccino.

티스토리툴바