Both sides previous revisionPrevious revisionNext revision | Previous revision |
spo600:aarch64_register_and_instruction_quick_start [2024/02/06 18:03] – [Starter Kit] chris | spo600:aarch64_register_and_instruction_quick_start [2025/02/19 16:54] (current) – [General-Purpose Integer Registers] chris |
---|
===== AArch64 Register and Instruction Quick Start ===== | ===== AArch64 Register and Instruction Quick Start ===== |
| |
This page contains very basic information on the AArch64 mode of the [[ARMv8]]/ARMv9 architecture: the [[Register|register]] layout and naming and the some basic instructions. | This page contains very basic information on the AArch64 mode of the [[ARMv8|ARMv8/ARMv9]] architecture: the [[Register|register]] layout and naming and some basic instructions. For more comprehensive information, see the references listed below. |
| |
===== Registers ===== | ===== Registers ===== |
| |
==== General-Purpose Registers ==== | ==== General-Purpose Integer Registers ==== |
| |
The aarch64 registers are named: | The aarch64 registers are named: |
* r0 through r30 - to refer generally to the registers | * r0 through r30 - to refer generally to the registers |
* x0 through x30 - for 64-bit-wide access (same registers) | * x0 through x30 - for 64-bit-wide access (same registers, specifically when accessed 64 bits at a time) |
* w0 through w30 - for 32-bit-wide access (same registers - upper 32 bits are either cleared on load or sign-extended (set to the value of the most significant bit of the loaded value)). | * w0 through w30 - for 32-bit-wide access (same registers, specifically accessed 32 bits (or less) at a time - upper 32 bits are either cleared on load or sign-extended (set to the value of the most significant bit of the loaded value)). |
| |
Register '31' is one of two registers depending on the instruction context: | Register '31' is one of two registers depending on the instruction context: |
* For all other instructions, it is a "zero" register, which returns 0 when read and discards data when written - named rzr (xzr, wzr) | * For all other instructions, it is a "zero" register, which returns 0 when read and discards data when written - named rzr (xzr, wzr) |
| |
Usage during [[Syscalls|syscall]]/function call: | Usage during [[Syscalls|syscall]] or [[procedure call]]: |
* **r0-r7 are used for arguments and return values; additional arguments are on the stack** | * r0-r7 are used for integer and pointer arguments; additional arguments are on the stack. Return value is in r0 (if an integer or pointer) |
* **For syscalls, the syscall number is in r8** | * For syscalls, the syscall number is in r8 |
* **r9-r15 are for temporary values (may get trampled)** | * r9-r15 are for temporary values - called function may clobber these values |
* r16-r18 are used for intra-procedure-call and platform values (avoid) | * r16-r18 are used for intra-procedure-call and platform values (avoid) |
* **The called routine is expected to preserve r19-r28 <nowiki>***</nowiki> These registers are generally safe to use in your program.** | * r19-r28 must be preserved by a called procedure. These registers are generally safe to use in a program that calls other procedures (functions/methods/subroutines). If you are writing a procedure, you must either avoid using these registers, or save the values in these registers and restore them before returning. |
* r29 and r30 are used as the frame register and link register (avoid) | * r29 and r30 are used as the frame register and link register (avoid) |
| |
cmp r0,r1 // compare register r0 with register r1. The comparison sets flags in the processor status register which affect conditional branches. | 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. | 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 | 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 | 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 | 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" | 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,r1 // move data from r1 to r0 |
mov r0,99 // load r0 with 99 (only certain immediate values are possible) | mov r0,99 // load r0 with 99 (only certain immediate values are possible) |
ret // return from subroutine (counterpart to bl) | 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 | 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 | 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" | stur r0,[r1,0] // store register r0 to the address pointed to by (r1 + 0) - the mnemonic means "store //unscaled// register" |
* Character values are indicated by quotation marks. Escapes (such as '\n') are permitted. | * Character values are indicated by quotation marks. Escapes (such as '\n') are permitted. |
* Destinations are given as the first argument (mov r0, r1 moves INTO r0 FROM r1; you can think of this as r0=r1). | * Destinations are given as the first argument (mov r0, r1 moves INTO r0 FROM r1; you can think of this as r0=r1). |
* For the LDR/STR instructions: you can append a character indicating the number of bits (lowest) to be loaded or stored: | * For the LDR/STR instructions: you can append a character to the register name indicating the number of bits (lowest) to be loaded or stored: |
* Q = Quadword = 64 bits | * Q = Quadword = 64 bits |
* D = Double word = 32 bits | * D = Double word = 32 bits |
* W = Word = 16 bits | * W = Word = 16 bits |
* B = Byte = 8 bits | * B = Byte = 8 bits |
| * For any LDR/STR instruction that is loading or storing less than 64 bits, use the narrow (32-bit) version of the register name. For example, ''STRB w14b,[x10]'' would store the lowest byte from register 14 to the address pointed to by register 10. |
| |
===== Resources ===== | ===== Resources ===== |
| |
* ARM Aarch64 documentation | * ARM Aarch64 documentation (many resources) |
* [[http://developer.arm.com/|ARM Developer Information Centre]] | * [[http://developer.arm.com/|ARM Developer Information Centre]] |
* [[https://developer.arm.com/docs/den0024/latest|ARM Cortex-A Series Programmer’s Guide for ARMv8-A]] | * [[https://developer.arm.com/docs/den0024/latest|ARM Cortex-A Series Programmer’s Guide for ARMv8-A]] |
* The //short// guide to the ARMv8 instruction set: [[https://www.element14.com/community/servlet/JiveServlet/previewBody/41836-102-1-229511/ARM.Reference_Manual.pdf|ARMv8 Instruction Set Overview]] ("ARM ISA Overview") | * Instruction References |
* The //long// guide to the ARMv8 instruction set: [[https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile|ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile]] ("ARM ARM") | * [[https://www.cs.princeton.edu/courses/archive/fall19/cos217/reading/ArmInstructionSetOverview.pdf|Armv8 Instruction Set Overview]] - this is an older document (and not up-to-date with the latest instructions) but it is accessible and compact, and serves as a good quick reference for the base instructions - effectively making a good index for the ARM ARM (below) |
* [[https://developer.arm.com/docs/ihi0055/latest/procedure-call-standard-for-the-arm-64-bit-architecture|Procedure Call Standard for the ARM 64-bit Architecture (AArch64)]] | * [[https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile|ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile]] (known as the "ARM ARM") - this is the "big" document with all the details |
* GAS Manual - Using as, The GNU Assembler: https:<nowiki>//</nowiki>sourceware.org/binutils/docs/as/ | * [[https://github.com/ARM-software/abi-aa/releases|ARM ABI documentation (on GitHub)]] - see specifically the Procedure Call Standard for the Arm 64-bit Architecture |
| * [[https://sourceware.org/binutils/docs/as/|GAS Manual - Using as, The GNU Assembler]] |
| |