; int __cdecl func(int x, int y)
func:
mov eax, [esp+4] ; x
add eax, [esp+8] ; x += y
ret
; int __stdcall func(int x, int y)
func:
mov eax, [esp+4] ; x
add eax, [esp+8] ; x += y
ret 8
Uses special ret instruction that removes n bytes off the stack AFTER it pops EIP off the stack
Do not confuse this with C style returns, this has nothing to do with the return value
; int __fastcall func(int a, int b, int c, int d, unsigned char e)
func:
mov eax, [esp+4] ; eax = c
add eax, [esp+8] ; eax += d
and eax, [esp+12]; eax &= e
add eax, ecx ; eax += a
add eax, edx ; eax += b
ret 12 ; why is it 12 even though e is a char?
; int __stdcall func(int a, int b, int c, int d, unsigned char e)
func:
mov eax, [esp+4] ; eax = a
add eax, [esp+8] ; eax += b
and eax, [esp+12]; eax &= c
add eax, [esp+16]; eax += d
add eax, [esp+20]; eax += e
ret 20
ECX and EDX do not need to be cleaned off the stack
Notice the offsets to each argument are now multiples of 8 instead of 4 like in x86
_func
_func@8
@func@8
int __cdecl func(int x, int y)
int __stdcall func(int x, int y)
int __fastcall func(int x, int y)
The type of calling convention can vary from compiler to compiler.