함수 호출 규약이란?
함수를 호출할 때 파라미터를 어떤 식으로 전달하는가에 대한 약속이다.
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
- 표준화된 규약은 아니며 컴파일러 업체에 따라 처리도 다르다
- 일반적으로 레지스터 내 하나 이상의 인수를 통과시켜 호출에 필요한 메모리 접근의 수를 줄인다
- 위의 두 호출 규약과는 다르게 인자가 들어오면 처음 두 개는 ECX와 EDX에 넣고 나머지 인자들만 오른쪽에서 왼쪽 순으로 스택에 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=¤tPage=1&postListTopCurrentPage=1&from=postView
'Study > Reversing' 카테고리의 다른 글
[Reversing] PE Header 개념 정리 & wow64 fs redirection (0) | 2020.09.21 |
---|---|
[Reversing] 어셈블리어 C언어로 변환하기 #1 (0) | 2020.09.14 |
[Reversing] abex' Crackme #1 (0) | 2020.09.14 |
[Reversing] Stack 구조와 Stack Frame (0) | 2020.09.08 |
[Reversing] 32bit 레지스터의 종류와 특징 (0) | 2020.09.07 |
댓글