AArch64 assembly - part 1

Author: Carmelo C.
Published: Feb 27, 2025 (updated)
assembly arm64 aarch64 coding

AArch64

Index

  1. Home
  2. Let’s break the ice
  3. Under the surface
  4. Under the microscope
  5. Cross-compilation
  6. Resources

Let’s break the ice

… or, let’s quickly generate some assembly code and run it.

Our very first program

Let’s write a small assembly program that does nothing but exits by leaving a specific return code. Copy and paste the following code into a file named answer.s.

/*
  File: answer.s
  Purpose: runs and, immediately, exits while leaving a return code that
           can be displayed through the OS
  Example:
    $ ./answer
    $ echo $?
    42
*/
.text

.global _start

_start:
    mov x0, #42  // x0 ←  42
    mov x8, #93  // x8 ←  93 (__NR_exit)
    svc #0       // syscall

The program can be assembled and linked with as and ld from binutils:

$ as -g answer.s -o answer.o

$ ld answer.o -o answer

NOTE: option -g in the first step is used to retain symbols in the code. It is optional but it can be used for debugging purposes.

Finally, as mentioned in the code, it can be run as follows:

$ ./answer

$ echo $?
42

Wut?

Oh! Wow! Indeed it works… and, apparently, it didn’t break anything. Good! Let’s dig a bit deeper and look at what we’ve done. Our file answer.s is a tiny text file abiding to a specific syntax. A few elements can be identified:

NOTE: for more info on syscall try man syscall. Hint:

$ grep 93 /usr/include/asm-generic/unistd.h | head -n1
#define __NR_exit 93