arm64
+keywords: arm64, aarch64, abi
+-
+
- 64bit synonyms:
arm64
,aarch64
+ - ISA type:
RISC
+ - Endianness:
little
,big
+
Registers
+General purpose registers
+bytes
+[7:0] [3:0] desc
+---------------------------------------------
+x0-x28 w0-w28 general purpose registers
+x29 w29 frame pointer (FP)
+x30 w30 link register (LR)
+sp wsp stack pointer (SP)
+pc program counter (PC)
+xzr wzr zero register
+
+++Write to
+wN
register clears upper 32bit.
Special registers per EL
+bytes
+[7:0] desc
+---------------------------------------------
+sp_el0 stack pointer EL0
+
+sp_el1 stack pointer EL1
+elr_el1 exception link register EL1
+spsr_el1 saved process status register EL1
+
+sp_el2 stack pointer EL2
+elr_el2 exception link register EL2
+spsr_el2 saved process status register EL2
+
+sp_el3 stack pointer EL3
+elr_el3 exception link register EL3
+spsr_el3 saved process status register EL3
+
+Addressing
+Offset
+ldr x0, [x1] // x0 = [x1]
+ldr x0, [x1, 8] // x0 = [x1 + 8]
+ldr x0, [x1, x2, lsl #3] // x0 = [x1 + (x2<<3)]
+ldr x0, [x1, w2, stxw] // x0 = [x1 + sign_ext(w2)]
+ldr x0, [x1, w2, stxw #3] // x0 = [x1 + (sign_ext(w2)<<3)]
+
+++Shift amount can either be
+0
orlog2(access_size_bytes)
. Eg for 8byte +access it can either be{0, 3}
.
Index
+ldr x0, [x1, 8]! // pre-inc : x1+=8; x0 = [x1]
+ldr x0, [x1], 8 // post-inc: x0 = [x1]; x1+=8
+
+Pair access
+ldp x1, x2, [x0] // x1 = [x0]; x2 = [x0 + 8]
+stp x1, x2, [x0] // [x0] = x1; [x0 + 8] = x2
+
+Procedure Call Standard ARM64 (aapcs64
)
+Passing arguments to functions
+-
+
- Integer/Pointer arguments
+
+reg arg +----------- +x0 1 +.. .. +x7 8 +
+ - Additional arguments are passed on the stack. Arguments are pushed
+
right-to-left (RTL)
, meaning next arguments are closer to currentsp
. +
+void take(..., int a9, int a10); + | | | ... | Hi + | +-->| a10 | | + +---------->| a9 | <-SP | + +-----+ v + | ... | Lo +
+
Return values from functions
+-
+
- Integer/Pointer return values
+
+reg size +----------------- +x0 64 bit +
+
Callee saved registers
+-
+
x19
-x28
+SP
+
Stack
+-
+
- grows downwards +
sp
must be 16byte aligned when used to access memory for r/w
+sp
must be 16byte aligned on public interface interfaces
+
Frame chain
+-
+
- linked list of stack-frames +
- each frame links to the frame of its caller by a
frame record
+-
+
- a frame record is described as a
(FP,LR)
pair
+
+ - a frame record is described as a
x29 (FP)
must point to the frame record of the current stack-frame +
++------+ Hi + | 0 | frame0 | + +->| 0 | | + | | ... | | + | +------+ | + | | LR | frame1 | + +--| FP |<-+ | + | ... | | | + +------+ | | + | LR | | current | +x29 ->| FP |--+ frame v + | ... | Lo +
+- end of the frame chain is indicated by following frame record
(0,-)
+ - location of the frame record in the stack frame is not specified +
Function prologue & epilogue
+-
+
- prologue
+
+sub sp, sp, 16 +stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30 +mov x29, sp // FP points to frame record +
+ - epilogue
+
+ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8] +add sp, sp, 16 +ret +
+
ASM skeleton
+Small assembler skeleton, ready to use with following properties:
+-
+
- use raw Linux syscalls (
man 2 syscall
for ABI)
+ - no
C runtime (crt)
+ - gnu assembler
gas
+
// file: greet.S
+
+#include <asm/unistd.h> // syscall NRs
+
+ .arch armv8-a
+
+ .section .text, "ax", @progbits
+ .balign 4 // align code on 4byte boundary
+ .global _start
+_start:
+ mov x0, 2 // fd
+ ldr x1, =greeting // buf
+ ldr x2, =greeting_len // &len
+ ldr x2, [x2] // len
+ mov w8, __NR_write // write(2) syscall
+ svc 0
+
+ mov x0, 0 // exit code
+ mov w8, __NR_exit // exit(2) syscall
+ svc 0
+
+ .balign 8 // align data on 8byte boundary
+ .section .rodata, "a", @progbits
+greeting:
+ .asciz "Hi ASM-World!\n"
+greeting_len:
+ .int .-greeting
+
+++man gcc:
+file.S
assembler code that must be preprocessed.
To cross-compile and run:
+> aarch64-linux-gnu-g++ -o greet greet.S -nostartfiles -nostdlib \
+ -Wl,--dynamic-linker=/usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 \
+ && qemu-aarch64 ./greet
+Hi ASM-World!
+
+++Cross-compiling on
+Ubuntu 20.04
, paths might differ on other distributions. +Compiling natively on arm64, specifying the dynamic linker should not be required.