본문 바로가기
Study/Reversing

[Reversing] x86(32 bit) / x64(64 bit) 호출규약

by Jamie Lim 2020. 9. 14.

함수 호출 규약이란?

  함수를 호출할 때 파라미터를 어떤 식으로 전달하는가에 대한 약속이다.

 

X86 함수 호출 규약 (32 bit)

1. __cdecl

  - C declaration이라는 의미로 C 프로그래밍 언어가 기원한 호출 규약이다

  - C 언어에서 사용되며 함수 호출이 반환된 뒤 caller(호출자)에서 스택을 정리한다 (함수 호출 전과 후의 ESP 위치가 같아야 됨!)

  - 매개변수를 스택에 push해 함수를 호출할 때 전달해준다 (오른쪽에서 왼쪽으로 인자를 스택에 넣는다)

  - 가변 인수 함수를 만들 때는 반드시 cdecl 호출 규약을 사용해야 한다

  - 함수 앞에 __을 추가한다

  - 함수 호출규약을 입력하지 않으면 기본값으로 __cdecl이 설정된다

 

예시 코드

#include <stdio.h>

int __cdecl cdecl_Test(int a, int b){
    int sum = 0;
    sum = a + b;
    return sum;
}

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

 

어셈블리 코드

 

 

2. __stdcall

  - Win32 API, C++, 오픈 왓콤 등의 표준 규약이다

  - cdecl 방식과 거의 비슷하지만 스택을 정리하는 곳이 caller(호출자)가 아닌 callee(호출된 함수)-> 함수에 스택 정리에 대한 코드가 있어 함수를 호출할 때마다 스택을 정리해주지 않아도 되어 크기가 cdecl보다 작다

  - 인자를 전달하는 방식은 cdecl과 동일하게 오른쪽에서 왼쪽이다

  - 함수 앞에 __을 추가하고 이름 뒤에는 @를 추가한다

 

예시 코드

#include <stdio.h>

int __stdcall stdcall_Test(int a, int b){
    int sum = 0;
    sum = a + b;
    return sum;
}

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

 

어셈블리 코드

 

 

3. __fastcall

  - 표준화된 규약은 아니며 컴파일러 업체에 따라 처리도 다르다

  - 일반적으로 레지스터 내 하나 이상의 인수를 통과시켜 호출에 필요한 메모리 접근의 수를 줄인다

  - 위의 두 호출 규약과는 다르게 인자가 들어오면 처음 두 개는 ECXEDX에 넣고 나머지 인자들만 오른쪽에서 왼쪽 순으로 스택에 PUSH한다

  - 모든 인자를 스택에 쌓지 않고 레지스터에 바로 넣어 다른 호출 규약에 비해 속도가 더 빠르다

  - 스택 정리는 stdcall처럼 callee(호출된 함수)에서 수행한다

 

위 호출규약 외에도 cdecl 호출 규약처럼 caller에서 스택을 정리하는 syscall, optink가 있고 callee에서 스택을 정리하는 pascal, register, sfecall 등이 있다.

 

예시 코드

#include <stdio.h>

int __fastcall cdecl_Test(int a, int b){
    int sum = 0;
    sum = a + b;
    return sum;
}

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

 

어셈블리 코드

 

 

X64 함수 호출 규약 (64 bit)

 64 bit 환경에서는 오로지 하나의 호출 규약만 지원한다. 바로 32 bit에서 본 fastcall이다. 델파이와 C++ 빌더에서 많이 사용하는데 32 bit는 앞의 인자 2개만 레지스터에 넘겼다면 64 bit에서는 8개까지 레지스터에 바로 넘길 수 있다고 한다. 그리고 32 bit와 다른 점은 가변 인자를 지원하기 위해 cdecl 호출 규약처럼 callee가 아닌 caller에서 스택을 정리한다는 점이다.

 그 외의 호출 규약들은 프로세서에서 허용은 하지만 보통 컴파일러에 의해 무시가 된다고 한다.

 

< 참고 >
http://blog.naver.com/PostView.nhn?blogId=luuzun&logNo=50190919742&categoryNo=0&parentCategoryNo=41&viewDate=&currentPage=1&postListTopCurrentPage=1&from=postView

댓글