AICollection Help

x86 Calling Convention 32-bit

The x86 calling convention is a set of rules that dictate how functions receive parameters and return values, how the stack is managed, and how registers are used. This ensures that code generated by different compilers can interoperate.

Key Points of the x86 Calling Convention

  1. Registers:

    • General-purpose registers: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP.

    • Stack pointer: ESP.

    • Base pointer: EBP.

  2. Parameter Passing:

    • Parameters are passed on the stack in right-to-left order.

    • The caller pushes the arguments onto the stack before calling the function.

  3. Return Values:

    • The primary return value is placed in EAX.

    • If a function returns a structure or a union, the address of the return value is passed as a hidden first parameter.

  4. Stack Management:

    • The stack must be 4-byte aligned at the point of a function call.

    • The caller is responsible for cleaning up the stack after the function call (cdecl) or the callee cleans up the stack (stdcall).

  5. Callee-saved Registers:

    • Registers EBX, ESI, EDI, EBP must be preserved by the callee.

    • The callee must save and restore these registers if it uses them.

Example

Here is an example of a simple function in x86 assembly that adds two integers:

global add add: mov eax, [esp+4] ; Load first argument into EAX add eax, [esp+8] ; Add second argument to EAX ret ; Return, result is in EAX

Explanation (1)

  • The function add takes two integer arguments passed on the stack.

  • It loads the first argument from [esp+4] into EAX.

  • It adds the second argument from [esp+8] to EAX.

  • The ret instruction returns to the caller, with the result in EAX.

Example with Stack Usage

Here is an example of a function that uses the stack to store local variables:

global sum_array sum_array: push ebp ; Save base pointer mov ebp, esp ; Set base pointer sub esp, 8 ; Allocate space for local variables mov dword [ebp-4], 0 ; Initialize sum to 0 mov dword [ebp-8], 0 ; Initialize index to 0 loop: mov eax, [ebp+8] ; Load array pointer mov ecx, [ebp-8] ; Load index mov edx, [ebp+12] ; Load array length cmp ecx, edx ; Compare index with array length jge end_loop ; If index >= length, exit loop mov eax, [eax+ecx*4] ; Load array element add [ebp-4], eax ; Add to sum inc dword [ebp-8] ; Increment index jmp loop ; Repeat loop end_loop: mov eax, [ebp-4] ; Move sum to return register mov esp, ebp ; Deallocate local variables pop ebp ; Restore base pointer ret ; Return

Explanation (2)

  • The function sum_array takes two arguments: a pointer to an array and the array length, both passed on the stack.

  • It saves the base pointer (EBP) and sets up the stack frame.

  • It allocates space for local variables.

  • It initializes the sum and index to 0.

  • It enters a loop to iterate over the array, loading each element, adding it to the sum, and incrementing the index.

  • After the loop, it moves the sum to the return register (EAX), deallocates the local variables, and restores the base pointer.

  • It returns with the sum in EAX.

These examples illustrate the basic principles of the x86 calling convention, including register usage, parameter passing, and stack management.

Last modified: 12 January 2025