x86 function call types

Learn x86 function call types with practical examples, diagrams, and best practices. Covers assembly, x86, call development techniques with visual explanations.

Understanding x86 Function Call Types

Hero image for x86 function call types

Explore the different calling conventions used in x86 assembly, including cdecl, stdcall, fastcall, and thiscall, and their impact on stack management and register usage.

Function calls are fundamental to structured programming, allowing code reuse and modularity. In x86 assembly, the way functions are called and how parameters are passed and return values are handled is governed by calling conventions. These conventions dictate aspects like parameter order, stack cleanup responsibilities, and register preservation. Understanding these differences is crucial for low-level programming, reverse engineering, and interfacing with libraries written in different languages.

Common x86 Calling Conventions

Several calling conventions have evolved for x86 architectures, each with its own set of rules. The most prevalent ones include cdecl, stdcall, fastcall, and thiscall. While they all achieve the goal of transferring control and data to a subroutine, their specific implementations lead to different performance characteristics and compatibility requirements.

flowchart TD
    A[Caller] --> B{Push Parameters};
    B --> C[CALL Instruction];
    C --> D[Callee Entry];
    D --> E{Function Body Execution};
    E --> F{Return Value Handling};
    F --> G[RET Instruction];
    G --> H[Caller Return];
    H --> I{Stack Cleanup (Who?)}

General flow of an x86 function call, highlighting key stages.

1. cdecl (C Declaration)

The cdecl calling convention is the default for C and C++ programs on x86. It is characterized by the caller being responsible for cleaning up the stack after the function returns. Parameters are pushed onto the stack from right to left. This convention supports variadic functions (functions with a variable number of arguments) because the caller knows exactly how many arguments it pushed and can clean them up accordingly.

; Example of cdecl call

; Caller side
push    arg3
push    arg2
push    arg1
call    my_cdecl_function
add     esp, 12 ; Caller cleans up 3 arguments (3 * 4 bytes)

; Callee side (my_cdecl_function)
; ... function body ...
ret     ; Callee does not clean up stack

Illustrative x86 assembly for a cdecl function call.

2. stdcall (Standard Call)

The stdcall convention is commonly used for Windows API functions. Unlike cdecl, the callee is responsible for cleaning up the stack. Parameters are pushed onto the stack from right to left, similar to cdecl. The ret instruction in stdcall functions often includes an immediate operand to pop the arguments off the stack, e.g., ret 12.

; Example of stdcall call

; Caller side
push    arg2
push    arg1
call    my_stdcall_function
; No stack cleanup by caller

; Callee side (my_stdcall_function)
; ... function body ...
ret     8 ; Callee cleans up 2 arguments (2 * 4 bytes)

Illustrative x86 assembly for a stdcall function call.

3. fastcall

The fastcall convention attempts to improve performance by passing some arguments in CPU registers instead of the stack. The specific registers used can vary between compilers and architectures (e.g., ECX and EDX are common on x86 for the first two arguments). Remaining arguments are pushed onto the stack from right to left. Stack cleanup is typically handled by the callee, similar to stdcall.

; Example of fastcall call (Microsoft Visual C++ convention)

; Caller side
mov     ecx, arg1 ; First argument in ECX
mov     edx, arg2 ; Second argument in EDX
push    arg3      ; Third argument on stack
call    my_fastcall_function

; Callee side (my_fastcall_function)
; ... function body using ECX, EDX, and [ESP+4] for arguments ...
ret     4 ; Callee cleans up stack arguments (arg3)

Illustrative x86 assembly for a fastcall function call, showing register usage.

4. thiscall

The thiscall convention is specifically used for non-static member functions of C++ classes. It's essentially a variation of stdcall or fastcall where the this pointer (a pointer to the object instance) is passed to the member function. Typically, the this pointer is passed in the ECX register (on MSVC) or pushed onto the stack as the first argument (on GCC/Clang). Other arguments follow the stdcall or cdecl rules, depending on the compiler and platform.

; Example of thiscall (Microsoft Visual C++ convention)

; Caller side
mov     ecx, OFFSET my_object ; 'this' pointer in ECX
push    arg1
call    MyClass::my_member_function

; Callee side (MyClass::my_member_function)
; ... function body using ECX for 'this' and [ESP+4] for arg1 ...
ret     4 ; Callee cleans up stack arguments

Illustrative x86 assembly for a thiscall member function call.