함수호출 규약
드림핵 강의를 보며
x86-64의 호출 규약에 따르면 이는 rdi="/bin/sh" 주소인 상태에서 system 함수를 호출 의한 것과 같습니다.
이런 문장을 읽으며 x86-64 호출 규약이 뭐지? 라는 생각이 들었습니다.
그 순간 "아!!, 함수 호출규약!!" 1학기 초 선배가 공부해 오라고 했던 것 이었습니다.
죄송합니다!! 숙제를 한학기나 지나서 해왔습니다. 😱😁😱
1. 함수호출 규약이란
정의: 함수 호출 및 반환에 대한 규칙이다.
함수 호출시 호출자의 상태, 반환 주소를 저장한다.
호출자는 피호출자가 요구하는 인자를 전달하며 실행 종료시 반환값 전달 받는다.
컴파일러는 cpu 아키텍쳐에 맞는 호출 규약 선택하며 컴파일러에 따라 적용하는 호출 규약이 다를 수 있다.
일반적으로 함수호출 규약을 적용하는 것은 컴파일러의 몫이었기에 프로그래머가 고수준 언어로 코드를 작성하면 컴파일러에 의해 호출 규약에 맞게 컴파일 된다. 이러한 이유로 대개의 프로그래머는 함수호출 규약을 몰라도 코드 작성에 큰 문제가 없었다.
2. x86 호출 규약
cdecl
사용 컴파일러: GCC, MSVC
특징
- 리눅스의 gcc가 x86 바이너리를 컴파일할때 일반적으로 사용하는 호출 규약이다.
- 레지스터를 사용하지 않고, 스택으로만 인자를 전달한다.
- 인자를 전달하기 위해 사용한 스택을 호출자가 정리한다.
- 마지막 인자부터 첫번째 인자까지 거꾸로 스택에 들어간다.
stdcall
사용 컴파일러: 사용 컴파일러: MSVC
특징
- 윈도우 API에서 기본적으로 사용되는 함수 호출 규약이다.
- cdecl 호출 규약을 변형하여 만들었다.
- 인자를 전달하기 위해 사용한 스택을 피호출자가 정리한다.
fastcall
사용 컴파일러: MSVC
특징
- 일부인자를 레지스터로 전달하여 속도를 향상 시키기위해 도입된 규약이다.
- 윈도우 운영체제의 성능 최적화를 위해 도입되었으며 다양한 컴파일러에서 지원한다.
- 처음 두 개의 인자를 각각
ecx,edx에 전달 후 나머지 인자는 마지막 부터 스택으로 전달한다.
thiscall
사용 컴파일러: MSVC
특징
- C++ 클래스 멤버 함수를 위한 함수 호출 규약이다.
this포인터를ecx로 넘기고 나머지 인자들은 모두 스택을 통해 전달한다.
3. x86-64 호출규약
System ABI
사용 컴파일러: GCC 특징
- System ABI는 ELF포멧, 링킹방법, 함수호출 규약등을 담고있다.
- 6개의 인자를
RDI,RSI,RDX,RCX,R8,R9순으로 저장하여 전달하며 더 많은 인자는 스택으로 전달한다. - 호출자가 인자 전달에 사용한 스택을 정리한다.
- 함수의 반환값은
RAX로 전달한다.