Tools and Your First AArch64 Program¶
Begin with a program you can build and explain, not a catalogue of instructions. You will produce a Linux AArch64 executable that writes one line and exits.
Course examples on GitHub
Before you start¶
You need terminal navigation and a Raspberry Pi with 64-bit Linux userspace. No electronics, C++ knowledge or root access is needed to run the examples. This course is Linux user-space assembly, not Pico firmware or a bootloader.
Outcome: build and inspect an executable, identify its entry point and distinguish kernel exit from a function return.
AArch64 names the 64-bit execution state; Linux tools often call the platform Arm64. A board model alone does not identify the installed toolchain.
Check and prepare the tools¶
Run on the Pi:
Expect aarch64, 64 and an AArch64 compiler target. A 64-bit kernel can host 32-bit programs, so check all three, not just uname. If packages are absent, installing them is an administrative change; review the package-manager prompt:
Create a new practice directory for this lesson. Repeat this pattern with a different suffix for later lessons; do not overwrite useful files.
Save and run the first program¶
Save as hello.S. GNU assembler directives begin with a dot; labels end in a colon. Instructions perform operations; comments beginning with // explain intent.
Expected output before the inspection commands:
The .o file is relocatable input, not the runnable program. ld resolves symbols and creates the executable; _start is its process entry. This deliberately small static example does not use a C runtime. Its adr reaches this nearby message; a later lesson covers range and relocation choices.
System calls are not function calls¶
Here svc enters the kernel, x8 selects a Linux operation and x0 receives its result. The numbers 64 and 93 are specific to Linux AArch64. They are not portable service numbers for bare-metal firmware or other operating systems. Check the target's installed asm-generic/unistd.h definitions rather than borrowing a table for x86.
A later C-callable routine instead enters with bl and returns with ret; it must not call exit when its caller expects a return. This is why the next lessons use a C driver for printing and checking results.
When the result differs¶
- Unknown
x0or instructions: check the native assembler target. - Exec format error: check the executable architecture and userspace.
- Missing tool: install the relevant package, not a random compiler repository.
- Exit 1: the example did not complete its single write; this is not a general retrying I/O implementation.
- Permission denied: check the directory mount and execute permissions before using
sudo.
Do not continue until you can rebuild in this directory and identify the entry symbol in disassembly.
Check your understanding¶
Which file is runnable, and why is replacing the last system call with ret incorrect here?
Compare your reasoning
The linked executable is runnable. No function caller placed a normal return address in LR at process entry; the program ends through Linux exit, not a return to C.