CALLING C FUNCTIONS
C Function Definition
When writing assembly code, I can call standard C functions like printf and exit using the gcc compiler but first I need a few changes in the code:
extern printf
extern exit
section .data
msg db "Hello World!", 0
msg1 db "Another Hello!", 0
fmt db "Output is: %s %s",10,0
section .text
global main
main:
push msg
push fmt
call printf
push 1
call exit
externis used to tell the assembler that the function is defined elsewhere;printfandexitare functions that are defined in the C standard library;- Instead of
global _start, I useglobal mainbecause thegcccompiler expects amain; PUSHis used to push data into the stack;CALLis used to call a function;
Stack Usage
The stack is a Last-In-First-Out (LIFO) data structure, meaning the last item pushed onto the stack is the first one to be popped off. Picture it like stacking plates in a cafeteria tray, the last plate I put on top is the first one I’ll take off when I need it.
Taking into account the previous example:
- My print function parameters are
printf(format, message); - I first
PUSH msgand thenPUSH fmtonto the stack;
This order might seem counterintuitive at first because I usually think of passing arguments in the order they are listed. However, the arguments are pushed in reverse order, ensuring that the function receives them in the correct sequence.
Compiling with GCC
Generate the object file using nasm and compile the final binary using gcc:
nasm -f elf32 -o program_name.o program_name.s
gcc -no-pie -m32 -o program_name program_name.o
-no-pieflag is used to disable the Position Independent Executable feature;-m32flag specifies the target architecture as 32 bits for x86;-fflag is used to specify the input format, in this case,elf32;
Position Independent Executable (PIE) is a feature that modern operating systems and compilers use to randomize the base address of executables in memory. This randomness helps to avoid security attacks like buffer overflow by making it difficult for attackers to predict memory layouts. However, in some cases, fixed addresses may be needed for compatibility or performance reasons.