함수 호출 규약 (x86, x64)

2025. 2. 10. 02:29·CS/Computer Architecture
728x90
반응형

Calling Convention | 함수 호출 규약

함수 호출 규약 : 함수의 호출 및 반환에 대한 약속

한 함수에서 다른 함수를 호출할 때 프로그램의 실행 흐름이 다른 함수로 이동한다. 이 호출된 함수가 반환되면 다시 원래의 함수로 돌아와서 기존의 실행 흐름을 이어나간다. 이때 호출하는 함수를 호출자(caller), 호출되는 함수를 피호출자(Callee)라고 한다. 

호출자는 피호출자가 요구하는 파라미터를 전달해줘야하고, 실행이 종료되면 반환 값을 전달받아야한다. 

 

Segment word size Calling Convention Parameters in register Stack cleanup by
32bits __cdecl   Caller
__stdcall   Callee
__fastcall ecx, edx Callee
__thiscall ecx Callee
64bits Microsoft x64 Calling Convention RCX, RDX, R8, R9 나머지 스택 Caller
System V AMD64 ABI (Linux x64) RDI, RSI, RDX, RCX, R8, R9 Caller

 

x86 Calling Convention

Linux의 경우, Calling Convention을 앞에 지정해주는 방식이 아니다. 

또한, __fastcall이 존재하지 않는다. 

__cdecl

  • 대부분의 32bits C프로그램에서 사용하는 사용하는 기본 호출 규약
  • 스택은 Caller에 의해 정리됨
  • 스택으로 인자가 전달됨

 

#include <stdio.h>

// __cdecl 제거: 리눅스에서는 필요 없음
int sum(int a, int b) {
    return a + b;
}

int main() {
    int s = sum(2, 3); // 함수 호출
    printf("%d\n", s); // 결과 출력
    return 0;
}

 

Assembly

pwndbg> disassem main
Dump of assembler code for function main:
   0x000011b4 <+0>:	lea    ecx,[esp+0x4]
   0x000011b8 <+4>:	and    esp,0xfffffff0
   0x000011bb <+7>:	push   DWORD PTR [ecx-0x4]
   0x000011be <+10>:	push   ebp
   0x000011bf <+11>:	mov    ebp,esp
   0x000011c1 <+13>:	push   ebx
   0x000011c2 <+14>:	push   ecx
   0x000011c3 <+15>:	sub    esp,0x10
   0x000011c6 <+18>:	call   0x10a0 <__x86.get_pc_thunk.bx>
   0x000011cb <+23>:	add    ebx,0x2e0d
   0x000011d1 <+29>:	push   0x3
   0x000011d3 <+31>:	push   0x2
   0x000011d5 <+33>:	call   0x119d <sum>
   0x000011da <+38>:	add    esp,0x8
   0x000011dd <+41>:	mov    DWORD PTR [ebp-0xc],eax
   0x000011e0 <+44>:	sub    esp,0x8
   0x000011e3 <+47>:	push   DWORD PTR [ebp-0xc]
   0x000011e6 <+50>:	lea    eax,[ebx-0x1fd0]
   0x000011ec <+56>:	push   eax
   0x000011ed <+57>:	call   0x1050 <printf@plt>
   0x000011f2 <+62>:	add    esp,0x10
   0x000011f5 <+65>:	mov    eax,0x0
   0x000011fa <+70>:	lea    esp,[ebp-0x8]
   0x000011fd <+73>:	pop    ecx
   0x000011fe <+74>:	pop    ebx
   0x000011ff <+75>:	pop    ebp
   0x00001200 <+76>:	lea    esp,[ecx-0x4]
   0x00001203 <+79>:	ret    
End of assembler dump.

 

pwndbg> disassem sum
Dump of assembler code for function sum:
   0x0000119d <+0>:	push   ebp
   0x0000119e <+1>:	mov    ebp,esp
   0x000011a0 <+3>:	call   0x1204 <__x86.get_pc_thunk.ax>
   0x000011a5 <+8>:	add    eax,0x2e33
   0x000011aa <+13>:	mov    edx,DWORD PTR [ebp+0x8]
   0x000011ad <+16>:	mov    eax,DWORD PTR [ebp+0xc]
   0x000011b0 <+19>:	add    eax,edx
   0x000011b2 <+21>:	pop    ebp
   0x000011b3 <+22>:	ret    
End of assembler dump.

 

Stack Frame

 

sum 함수 호출 전 후

해당 스택을 보면 인자값이 호출하기 전에 push 되는 것을 확인할 수 있다. 

또한, 함수 반환 이후, sub esp, 0x8 등으로 Caller가 함수를 정리한다. 

 

__stdcall

  • 주로 WinAPI 32 함수들이 __stdcall을 따름
  • 스택은 Callee에 의해 정리됨
  • 스택으로 인자가 전달됨
#include <stdio.h>

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

int main()
{
	int s = sum(2, 3);
	printf("%d", s);
	return 0;
}

 

__fastcall

  • 두 인자들이 4바이트보다 작거나 같다면 edx, ecx에 담아두고 사용함
  • 나머지는 스택으로 전달
  • 레지스터를 이용하기 때문에 함수 호출 비용을 줄일 수 있음
  • Callee에 의해 스택을 정리함

__thiscall

  • C++에서 사용하는 함수 호출 규약
  • this 포인터는 ecx에 저장되고 나머지는 스택에 저장
  • Callee에 의해 스택을 정리함

 

x64 Calling Convention

Microsoft x64 Calling Convention

  • 정수 파라미터는 RCX, RDX, R8, R9로 전달됨
  • 부동 소수점 파라미터는 XMM0L, XMM1L, XMM3L로 전달됨
  • 16바이트 파라미터는 참조로 전달됨
  • 파라미터가 많으면, 레지스터 이외의 부분은 스택으로 전달됨
  • RAX로 반환됨
  • Caller가 스택을 정리함

System V amd64 ABI

  • RDI, RSI, RDX, RC, R8, R9 로 전달됨
  • 파라미터가 많으면, 레지스터 이외의 부분은 스택으로 전달됨
  • Caller가 스택을 정리함 
  •  

 

 

출처

- https://learn.microsoft.com/ko-kr/cpp/build/x64-calling-convention?view=msvc-170

 

x64 호출 규칙

기본 x64 호출 규칙의 세부 정보에 대해 알아봅니다.

learn.microsoft.com

- https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/linux-x64-calling-convention-stack-frame

 

Linux x64 Calling Convention: Stack Frame | Red Team Notes

In 64-bit Linux system, function arguments of type integer/pointers are passed to the callee function in the following way: This lab and conclusions are based on the following C program compiled on a 64-bit Linux machine: Let's now see how arguments are pa

www.ired.team

 

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'CS > Computer Architecture' 카테고리의 다른 글

[Assembly] 산술 연산  (0) 2024.09.27
[Assembly] 데이터 이동  (1) 2024.09.20
Static Link vs Dynamic Link  (0) 2024.09.05
함수의 프롤로그 & 에필로그  (0) 2024.08.22
Register  (1) 2024.08.16
'CS/Computer Architecture' 카테고리의 다른 글
  • [Assembly] 산술 연산
  • [Assembly] 데이터 이동
  • Static Link vs Dynamic Link
  • 함수의 프롤로그 & 에필로그
min_zu
min_zu
  • min_zu
    민주제도
    min_zu
  • 전체
    오늘
    어제
    • ._. (176)
      • AI (2)
        • DeepLearning (2)
        • CS231n (0)
      • Web (2)
        • ReactJS (0)
      • CS (83)
        • OS (7)
        • Data Structure (23)
        • Computer Architecture (8)
        • Computer Network (20)
        • Algorithm (25)
      • Linux (3)
        • KaliLinux (0)
        • Docker (1)
      • Hacking (83)
        • Write Up (25)
        • Pwnable (13)
        • Reversing (2)
        • Cryptography (12)
        • Web Hacking (4)
        • Window (6)
        • Network (7)
        • Web3 (13)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Web
    DataStructure
    Mac
    UTM
    WinAFL
    OS
    DeepLearning
    Tree
    Sort
    ComputerArchitecture
    Linux
    Graph
    Search
    AI
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
min_zu
함수 호출 규약 (x86, x64)
상단으로

티스토리툴바