This is the fifth post about x86 assembly. In this post I will show how to call functions in x86 assembly.
Below is a simple program that has three functions besides main.
global main extern printf section .text main: mov rdi, 5 call times2 mov rdi, rax call print_value call exit times2: push rbp mov rbp, rsp mov rax, rdi add rax, rax mov rsp, rbp pop rbp ret print_value: push rbp mov rbp, rsp push rdi mov rdi, fmt pop rsi mov rax, 0 call printf wrt ..plt mov rsp, rbp pop rbp ret exit: mov rdi, 0 ; exit code 0 mov rax, 60 ; system call for exit syscall section .data fmt: db "The value is %d", 10, 0
Passing values to functions
The code above is following the Linux 64-bit ABI where the first six arguments(integers and pointers) are passed through registers. You could also pass the arguments on the stack or hardcoded memory locations.
Function prologue and epilogue
The beginning and the end in the functions
print_value is called the function prologue and epilogue.
push rbp mov rbp, rsp ... mov rsp, rbp pop rbp ret
This a convention for preparing the stack for usage. The prologue creates a new stack frame for the called function and the epilogue restores the stack frame for the calling function.