Lesson 8 of 10
Calling C Functions from ASM
You'll learn how to call C such as printf and malloc from . This lets you reuse existing code and keep assembly for the parts that need it.
; Link with libc: nasm -f elf64 main.asm -o main.o && gcc main.o -o main -no-pie
; (gcc handles linking libc and the C runtime startup)
; Entry point becomes main instead of _start
extern printf
extern malloc
extern free
extern strlen
extern puts
section .data
fmt_int db "Value: %ld", 10, 0 ; printf format string (null-terminated)
fmt_str db "Hello, %s!", 10, 0
mystr db "World", 0
section .text
global main
main:
push rbp
mov rbp, rsp
sub rsp, 16 ; align and reserve locals
; printf("Value: %ld\n", 42)
lea rdi, [rel fmt_int] ; format string (1st arg)
mov rsi, 42 ; integer (2nd arg)
xor eax, eax ; rax = 0 (no vector regs used — required for variadic!)
call printf
; printf("Hello, %s!\n", "World")
lea rdi, [rel fmt_str]
lea rsi, [rel mystr]
xor eax, eax
call printf
; puts("simple string")
lea rdi, [rel mystr]
call puts
; malloc(128) — allocate 128 bytes
mov rdi, 128
call malloc ; rax = pointer to 128 bytes (or NULL)
mov r12, rax ; save pointer
; strlen(pointer)
mov rdi, r12
call strlen ; rax = length
; free(pointer)
mov rdi, r12
call free
; return 0 from main
xor eax, eax
leave ; equivalent to: mov rsp, rbp; pop rbp
ret# Assemble and link with libc via gcc
nasm -f elf64 main.asm -o main.o
gcc main.o -o main -no-pie
./main
# -no-pie: disable position-independent executable
# (PIE changes how globals/extern are addressed, complicates assembly)
# See what symbols your .o needs from external libs:
nm -u main.o
# See what libc functions a compiled binary calls:
objdump -d main | grep call
ltrace ./main # trace library calls at runtime
strace ./main # trace syscalls at runtimeFinished reading?Mark it done to track your progress.
Tip: use the ← and → keys to move between lessons.