Hands-on Example: eatsyscall64 (NASM + ld)
Hands-on Example: eatsyscall64 (NASM + ld)
This page demonstrates a complete example of creating, assembling, linking, and running a simple assembly program on Linux using NASM and ld.
Example overview
The program prints the message "Eat at Joe’s!" to standard output and exits. It directly uses Linux system calls to interact with the kernel.
Source code: eatsyscall64.asm
Below is the full source code of the example program.
SECTION .data ; Section containing initialized data EatMsg: db "Eat at Joe's!", 10 EatLen: equ $ - EatMsg ; Compute the length of the string
SECTION .bss ; Section containing uninitialized data
SECTION .text ; Section containing code global _start ; Linker needs this to find the entry point
_start:
mov rax, 1 ; Code for sys_write system call mov rdi, 1 ; File descriptor 1 = Standard Output mov rsi, EatMsg ; Address of message mov rdx, EatLen ; Length of message syscall ; Invoke kernel
mov rax, 60 ; Code for sys_exit system call mov rdi, 0 ; Exit code 0 syscall ; Invoke kernel
Explanation
- SECTION .data: defines variables with initial values.
- SECTION .bss: for variables without initial values.
- SECTION .text: contains the program’s instructions.
- global _start: tells the linker where execution begins.
- sys_write and sys_exit are Linux kernel system calls identified by numbers in `rax`.
When run, the program writes the message to standard output and exits cleanly.
Assembling
To translate the program into an object file, use NASM (Netwide Assembler):
$ nasm -f elf64 -g -F dwarf eatsyscall64.asm -o eatsyscall64.o
Explanation of options:
- `-f elf64`: generate 64-bit ELF object file.
- `-g`: include debug information.
- `-F dwarf`: specify DWARF format for debugging.
- `-o eatsyscall64.o`: name of the output file.
Linking
Next, link the object file into an executable using ld (the GNU linker):
$ ld -o eatsyscall64 eatsyscall64.o
This command creates an executable file named `eatsyscall64`.
Running
Execute the program directly:
$ ./eatsyscall64
Eat at Joe’s!
Lessons learned
- Assembly requires precise control of registers and system calls.
- Every instruction has a specific meaning and side effect.
- Proper structure and comments make low-level code readable.
Although the program is small, it illustrates the full process of creating an executable from source code on a real system.