Assembly ARM64: Hello World!
I started learning x86_64 assembly a few months ago, but after packing away my PC, I'm now stuck with my Apple Silicon MacBook.
(ᵕ—ᴗ—)
So I've decided to learn arm64 instead.
First, I defined the entrypoint of the program using .global _start
— telling the linker (ld
) to use this.
Then, .align 4
indicates that we want to use multiples of 2^4
of memory addresses to store code/data.
0 = 0x00 = 0000 0000 16 = 0x10 = 0001 0000 32 = 0x20 = 0010 0000 48 = 0x30 = 0011 0000
Next, I added the hello_world
label and set its value to hello, world!
using the .asciz
directive to define it as a null-terminated ASCII.
.global _start .align 4 _start: ... hello_world: .asciz "hello, world!"
From _start
, we'll need to achieve 2 things — printing the data and exiting the program. By the way, this is an awesome website with syscall lists.
Let's take a look at the below.
_start: mov x0, #1 adrp x1, hello_world@PAGE add x1, x1, hello_world@PAGEOFF mov x2, #13 mov x16, #4 svc #0x80
Jumping to the line mov x16, #4
first, the x16
register (arm64) stores the number of the syscall that will be used. In this case, it's 4 - write
.
To use write
, we need to pass in the below arguments.
x0 - unsigned int fd (file descriptor) x1 - const char *buf (buffer address) x2 - size_t count (buffer size)
mov x0, #1
sets the value of x0
to 1
which is stdout
.
adrp x1, hello_world@PAGE
and add x1, x1, hello_world@PAGEOFF
calculates the exact address of our hello_world
data. I will dive deeper in another blog post on this.
mov x2, #13
sets the value of x2
to 13
, which is the length of hello_world
.
Next, svc #0x80
is a supervisor call to invoke kernel services to execute the syscall.
Finally, the last 3 instructions are much simpler. Again, looking at mov x16, #1
first. This instruction targets syscall 1
which corresponds with exit
that takes in a single argument of x0
of type int
— the exit code for the program.
In our case, mov x0, #0
means it will exit with 0
— running successfully.
_start: ... mov x0, #0 mov x16, #1 svc #0x80
.global _start .align 4 _start: mov x0, #1 adrp x1, hello_world@PAGE add x1, x1, hello_world@PAGEOFF mov x2, #13 mov x16, #4 svc #0x80 mov x0, #0 mov x16, #1 svc #0x80 hello_world: .asciz "hello, world!"