In this first program we simply return the exit code 0. Here is how it works:
global _start
section .text
_start:
mov rax, 60
mov rdi, 0
syscall
global _start
: This makes the_start
label globally accessible, so the linker and operating system can find the entry point for the program.section .text
: This defines the section of the program where the executable code resides._start
: This is the entry point of the program. When the program runs, execution starts here.mov rax, 60
: Moves the value 60 into therax
register. In Linux,60
is the syscall number forexit
.mov rdi, 0
: Moves the value0
into therdi
register. This is the exit status code that theexit
syscall will use.syscall
: This makes a system call to the kernel. Here, it uses theexit
syscall to terminate the program and return the exit status code0
.
A syscall, or system call, is a way for programs to interact with the operating system's kernel. Syscalls provide a controlled interface for user-level applications to request services and resources managed by the OS. These requests can include tasks such as file manipulation, process control, and communication.
- Request: The program prepares a syscall request by placing the syscall number (which identifies the desired service) and any necessary arguments in specific registers.
- Interrupt: The program triggers a software interrupt (often via the syscall instruction on x86_64) to switch from user mode to kernel mode.
- Execution: The kernel receives the request, validates it, and executes the corresponding kernel function.
- Return: The kernel places the result of the syscall back into a predefined register and switches back to user mode, returning control to the calling program.
Syscalls are fundamental to the functionality of an operating system, as they provide a secure and efficient way for user applications to access kernel services.
This is a Bash script that assembles, links, and runs the assembly code.
#!/usr/bin/env bash
mkdir -p ./bin/
nasm -f elf64 main.asm -o ./bin/main.o
ld bin/main.o -o ./bin/main
chmod +x ./bin/main
./bin/main
echo "[Exited with error code: $?]"
#!/usr/bin/env bash
: This shebang line tells the system to use the Bash shell to interpret this script.mkdir -p ./bin/
: Creates a directory namedbin
if it doesn't already exist. The-p
flag ensures that no error is thrown if the directory already exists.nasm -f elf64 main.asm-o ./bin/main.o
: Assembles themain.asm
file into an object file namedmain.o
, using theELF64
format, and places it in thebin
directory.ld bin/main.o -o ./bin/main
: Links themain.o
object file to create an executable namedmain
in thebin
directory.chmod +x ./bin/main
: Changes the permissions of themain
file to make it executable../bin/main
: Executes the main program.echo "[Exited with error code: $?]"
: Prints the exit code of themain
program to the terminal.$?
holds the exit code of the last executed command.
The Executable and Linkable Format (ELF) is a file format used for executables, object files, shared libraries, and core dumps in Unix-like operating systems, including Linux.
- Header: Contains metadata about the file, including the type (executable, shared library, etc.), architecture (64-bit), entry point address, and offsets to other sections of the file.
- Program Header Table: Contains information needed by the system loader to create a process image suitable for execution. This includes segments such as the text (code), data, and read-only data (rodata).
- Section Header Table: Describes the sections in the file, such as the symbol table, string table, and various other data required for linking.
- Sections:
.text
: Contains the executable code..data
: Contains initialized data..bss
: Contains uninitialized data..rodata
: Contains read-only data, such as constants and string literals.
- Dynamic Linking Information: Contains information and pointers needed for dynamic linking and loading shared libraries.
- Loader Reads the Header: The system loader reads the ELF header to understand where the code is and what it needs to run.
- Creates Segments: The loader creates segments in memory according to the program header table.
- Loads Sections: The loader copies the contents of the .text, .data, and other sections into the appropriate memory segments.
- Starts Execution: The loader jumps to the entry point address specified in the header to start executing the code.
Try setting the error code to 8
instead.