CLOSE

Register Based Parameter Passing

As we already studied there are different calling convention of passing parameters to a function.

What is Register-Based Parameter Passing?

Register-based parameter passing involves using the CPU's registers to hold the parameters that a function needs. In the x86 architecture, specific calling conventions define which registers are used for parameter passing. For instance, the fastcall convention typically uses ECX and EDX for the first two parameters.

How Register-Based Parameter Passing Works

When a function is called:

  1. Parameter Loading: The calling code loads the parameter values into predefined registers.
  2. Function Call: The function is invoked using the call instruction.
  3. Parameter Access: The called function accesses the parameters directly from the registers.
  4. Function Return: The ret instruction is used to return control to the calling code.

Advantages of Register-Based Parameter Passing

  1. Speed: Accessing registers is faster than accessing memory (stack).
  2. Efficiency: Fewer instructions are needed to manage parameters, reducing code size and execution time.
  3. Simpler Code: Direct register access simplifies the process of passing and retrieving parameters.

Disadvantages of Register-Based Parameter Passing

  1. Limited Parameters: The number of parameters is limited by the number of available registers.
  2. Register Pressure: High usage of registers for parameters can limit their availability for other tasks, leading to increased use of memory for intermediate values.
  3. Calling Convention Dependency: Code must adhere to specific calling conventions, reducing portability across different conventions or architectures.

Practical Examples

Simple Function with Two Parameters

Here's an example demonstrating how to pass two parameters to a function using registers:

section .text
global _start

_start:
    ; Load parameters into registers
    mov ecx, 5        ; First parameter (multiplier)
    mov edx, 7        ; Second parameter (multiplicand)
    
    ; Call the multiply function
    call multiply

    ; EAX now contains the result of the multiplication

    ; Exit the program
    mov eax, 1        ; sys_exit
    xor ebx, ebx      ; Exit code 0
    int 0x80          ; Interrupt to exit

; Define the multiply function
multiply:
    ; ECX = first parameter
    ; EDX = second parameter
    imul eax, ecx, edx ; EAX = ECX * EDX

    ; Return to the caller
    ret

In this example:

  • Parameters are loaded into ECX and EDX.
  • The multiply function multiplies these parameters and stores the result in EAX.
  • The ret instruction returns control to the caller.

Function with More than Two Parameters

When more than two parameters are needed, additional parameters are typically passed on the stack:

section .text
global _start

_start:
    ; Load parameters into registers
    mov ecx, 5        ; First parameter
    mov edx, 7        ; Second parameter
    push dword 3      ; Third parameter (push onto the stack)
    
    ; Call the add_and_multiply function
    call add_and_multiply
    add esp, 4        ; Clean up the stack (1 * 4 bytes)
    
    ; EAX now contains the result of the operation

    ; Exit the program
    mov eax, 1        ; sys_exit
    xor ebx, ebx      ; Exit code 0
    int 0x80          ; Interrupt to exit

; Define the add_and_multiply function
add_and_multiply:
    push ebp
    mov ebp, esp

    ; Access the third parameter from the stack
    mov eax, [ebp+8]  ; Third parameter
    
    ; Perform the addition and multiplication
    add eax, ecx      ; EAX = EAX + ECX
    imul eax, eax, edx ; EAX = EAX * EDX

    pop ebp
    ret

In this example:

  • The first two parameters are passed in ECX and EDX.
  • The third parameter is passed on the stack.
  • The add_and_multiply function adds the third parameter to the first, then multiplies the result by the second parameter.