One of the easiest ways to get started using ARM64 (also known as AARCH64) is with Docker or Virtual Box. While setting up a Raspberry Pi with an AArch64 OS is doable (particularly with OpenSUSE), it can be much faster to just emulate a linux box or image on an x86 based machine. This post assumes you already have docker installed and running.
Docker
First, start a Debian command line:
docker run -it debian /bin/bash
It’s as simple as that.
Hello AArch64
There are two main dependencies for working with AArch64: qemu
and
aarch64-linux-gnu-gcc
. The first emulates execution of AArch64 binaries
and the latter is a cross compiler to AArch64.
The following commands compiles and prints the classic “hello, world\n”
message: (Note, replace vim
with your favorite editor i.e. emacs
)
apt-get update
apt-get install -y qemu-user-static gcc-aarch64-linux-gnu vim
vim hello.c
aarch64-linux-gnu-gcc -static hello.c -o hello
qemu-aarch64-static hello
Where hello.c
is:
#include <stdio.h>
int main(void) {
printf("hello, world\n");
return 0;
}
In Debian, running qemu-aarch64-static hello
is the same as running
./hello
for an AArch64 binary hello
. This does not necessarily
happpen with other operating systems.
Examine the Binary
To inspect the binary, it will be easier to look at the non-statically compiled version, so re-run gcc:
aarch64-linux-gnu-gcc hello.c -o hello
aarch64-linux-gnu-objdump -d hello > hello.dmp
vim hello.dmp
And inspect the <main>:
address to see the disassembly:
0000000000000828 <main>:
828: a9bf7bfd stp x29, x30, [sp, #-16]!
82c: 910003fd mov x29, sp
830: 90000000 adrp x0, 0 <_init-0x658>
834: 91238000 add x0, x0, #0x8e0
838: 97ffffa6 bl 6d0 <puts@plt>
83c: 52800000 mov w0, #0x0 // #0
840: a8c17bfd ldp x29, x30, [sp], #16
844: d65f03c0 ret
Another way of looking at the pre-linked assembly code is of course to
just ask GCC for it: aarch64-linux-gcc hello.c -S
and then open
hello.s
:
.arch armv8-a
.file "hello.c"
.section .rodata
.align 3
.LC0:
.string "hello, world"
.text
.align 2
.global main
.type main, %function
main:
stp x29, x30, [sp, -16]!
add x29, sp, 0
adrp x0, .LC0
add x0, x0, :lo12:.LC0
bl puts
mov w0, 0
ldp x29, x30, [sp], 16
ret
.size main, .-main
.ident "GCC: (Debian 6.3.0-18) 6.3.0 20170516"
.section .note.GNU-stack,"",@progbits
Examining the differences between these files can be interesting, for
example the add
instruction below main:
was changed to a mov
instruction in the actual binary.
Compile Dynamically-Linked Binary
Why is the -static
flag needed for cross-compiling the AArch64 binaries?
Without it, you will see something like this message:
root@30941edc6d88:~# ./hello
/lib/ld-linux-aarch64.so.1: No such file or directory
See “Qemu AArch64 User-Space Emulation” on just the topic.