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

Repository

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