// Name: callconv_quiz.c
// Compile: gcc -o callconv_quiz callconv_quiz.c -m32
int __attribute__((cdecl)) sum(int a1, int a2, int a3){
return a1 + a2 + a3;
}
void main(){
int total = 0;
total = sum(1, 2, 3);
}
main:
0x080483ed <+0>: push ebp
0x080483ee <+1>: mov ebp,esp
0x080483f0 <+3>: sub esp,0x10
0x080483f3 <+6>: mov DWORD PTR [ebp-0x4],0x0
0x080483fa <+13>: (a)
0x080483fc <+15>: (b)
0x080483fe <+17>: (c)
0x08048400 <+19>: call 0x80483db <sum>
0x08048405 <+24>: (d)
0x08048408 <+27>: mov DWORD PTR [ebp-0x4],eax
0x0804840b <+30>: nop
0x0804840c <+31>: leave
0x0804840d <+32>: ret
x86 아키텍처이므로, 함수의 인자들을 스택에 거꾸로 push 한다.
*main+6 에서 지역변수인 total 함수를 스택에 넣었고,
함수의 인자가 1, 2, 3이므로 가장 먼저 3을 스택에 넣어야 한다.
push 0x3
다음으로 2를 스택에 넣어야 하므로
push 0x2
다음으로 1를 스택에 넣어야 하므로
push 0x1
x86 아키텍처이므로, 호출자가 스택 프레임을 정리한다.
4byte의 함수 인자를 총 3개 push 했으므로, rsp를 12byte만큼 더해준다.
따라서 add esp, 0xc
// Name: callconv_quiz2
// Compile: gcc -o callconv_quiz2 callconv_quiz2.c
int sum(int a1, int a2, int a3){
return a1 + a2 + a3;
}
void main(){
int total = 0;
total = sum(1, 2, 3);
}
main:
0x00000000004004f2 <+0>: push rbp
0x00000000004004f3 <+1>: mov rbp,rsp
0x00000000004004f6 <+4>: sub rsp,0x10
0x00000000004004fa <+8>: mov DWORD PTR [rbp-0x4],0x0
0x0000000000400501 <+15>: (a)
0x0000000000400506 <+20>: (b)
0x000000000040050b <+25>: (c)
0x0000000000400510 <+30>: call 0x4004d6 <sum>
0x0000000000400515 <+35>: mov DWORD PTR [rbp-0x4],eax
0x0000000000400518 <+38>: nop
0x0000000000400519 <+39>: leave
0x000000000040051a <+40>: ret
x86-64 아키텍처에서는 함수 인자를 rdi, rsi, rdx, rcx, r8, r9 에 차례로 저장하고
나머지 인자들은 스택에 push한다.
가장 먼저 세번째 인자인 3을 edx에 대입한다.
mov edx, 0x3
다음으로 2를 esi에 대입한다.
mov esi, 0x2
다음으로 1을 edi에 대입한다.
mov edi, 0x2