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!"