Table of Contents

AArch64 Register and Instruction Quick Start

This page contains very basic information on the AArch64 mode of the ARMv8/ARMv9 architecture: the register layout and naming and some basic instructions. For more comprehensive information, see the references listed below.

Registers

General-Purpose Registers

The aarch64 registers are named:

Register '31' is one of two registers depending on the instruction context:

Usage during syscall/function call:

See the ARM Procedure Call Reference for details.

Floating-Point and SIMD Registers

Aarch64 also defines a set of large registers for floating-point and single-instruction/multiple-data (SIMD) operations. For details, refer to the ARM documentation.

Instructions

Starter Kit

These instructions are sufficient to complete the SPO600 Assembler Lab; remember to replace the generic register names with ones that specify width (for example, replace “r0” with “x0” or “w0”).

 add r0,r1,r2      // load r0 with r1+r2
 add r0,r1,99      // load r0 with r1+99
 adr r0,label      // load r0 with the address label (this actually calculates an address from the 
 Program Counter plus an offset)
 adrp r0,label     // load r0 with the 4K page containing label (this calculates an address from the Program Counter plus an offset, and is often followed by an ADD instruction so that the register points exactly to the label)
 bl label          // branch (with link) to label - this is a procedure / subroutine / function call
 br label          // branch to label - this is a goto
 br register       // branch to the address in register
 b.eq label        // branch to label if equal
 b.ne label        // branch to label if not equal
 b.lt label        // branch to label if less
 b.gt label        // branch to label if greater
 cmp r0,r1         // compare register r0 with register r1. The comparison sets flags in the processor status register which affect conditional branches.
 cmp r0,99         // compare the number 99 with register r0. The comparison sets flags in the processor status register which affect conditional branches.
 ldr r0,[r1,0]     // load register r0 from the address pointed to by (r1 + (0 * size)) where size is 8 bytes for 64-bit stores, 4 bytes for 32-bit stores. The ",0" is not required.
 ldr w0,[r1,0]     // like above but reads 32 bits only - note the use of w0 instead of r0 for the source register name.  The ",0" is not required.
 ldrb w0,[r1,0]    // like above but reads 1 byte (8 bits) only - note the use of w0 for the source register name. The ",0" is not required.
 ldur r0,[r1,0]    // load register r0 from the address pointed to by (r1 + 0) - the mnemonic means "load unscaled register".  The ",0" is not required.
 mov r0,r1         // move data from r1 to r0
 mov r0,99         // load r0 with 99 (only certain immediate values are possible)
 ret               // return from subroutine (counterpart to bl)
 str r0,[r1,0]     // store register r0 to address pointed to by (r1 + (0 * size)) where size is 8 bytes for 64-bit stores
 strb w0,[r1,0]    // like str but writes one byte only - note the use of w0 for the source register name
 stur r0,[r1,0]    // store register r0 to the address pointed to by (r1 + 0) - the mnemonic means "store //unscaled// register"
 svc 0             // perform a syscall
 msub r0,r1,r2,r3  // load r0 with r3-(r1*r2) (useful for calculating remainders)
 madd r0,r1,r2,r3  // load r0 with r3+(r1*r2)
 mul r0,r1,r2      // load r0 with r1*r2 (actually an alias - see ARM ARM)
 push r0           // push r0 onto the stack
 pop r0            // pop r0 off the stack
 udiv r0,r1,r2     // unsigned - divide r1 by r2, places quotient into r0 - remainder is not calculated (use msub)

Note the syntax:

Resources