The STP (Store Pair) instruction in ARM64 is used to store two registers into memory in a single operation. It is commonly used to save registers onto the stack or to store data in memory efficiently.
STP
Rt: The first register to store.Rt2: The second register to store.BaseRegister: The base register that holds the memory address.Offset: The optional offset added to the base address.
// Store x0 and x1 into memory at the address in x2
STP x0, x1, [x2]
// Store x0 and x1 into memory at the address in x2 with an offset of 16 bytes
STP x0, x1, [x2, #16]
The following C-code demonstrates a scenario that could translate to the use of the STP instruction:
void save_registers(uint64_t *memory, uint64_t reg1, uint64_t reg2) {
memory[0] = reg1; // Corresponds to storing the first register
memory[1] = reg2; // Corresponds to storing the second register
}
In assembly, this could translate to:
// Assuming x0 = memory, x1 = reg1, x2 = reg2
STP x1, x2, [x0]
This is common to see when calling functions. For example, when a function is called, the caller may need to save certain registers onto the stack to preserve their values. This is often done using the STP instruction to save multiple registers efficiently:
// Save x29 (frame pointer) and x30 (link register) onto the stack
STP x29, x30, [sp, #-16]!
// Restore x29 and x30 from the stack
LDP x29, x30, [sp], #16
In this example, the STP instruction is used to save the frame pointer and link register at the beginning of a function, and the LDP (Load Pair) instruction is used to restore them at the end of the function.
The LDR (Load Register) instruction in ARM64 is used to load a value from memory into a register. It is commonly used to retrieve data from memory for processing.
LDR
Rt: The register to load the value into.BaseRegister: The base register that holds the memory address.Offset: The optional offset added to the base address.
// Load the value at the address in x2 into x0
LDR x0, [x2]
// Load the value at the address in x2 with an offset of 16 bytes into x0
LDR x0, [x2, #16]
The following C-code demonstrates a scenario that could translate to the use of the LDR instruction:
uint64_t load_register(uint64_t *memory) {
return memory[0]; // Corresponds to loading the value from memory
}
In assembly, this could translate to:
// Assuming x0 = memory, x1 = destination register
LDR x1, [x0]
This is common to see when accessing function arguments or local variables stored in memory. For example, when a function accesses a variable stored on the stack, the LDR instruction is often used:
// Load a variable from the stack into x0
LDR x0, [sp, #8]
In this example, the LDR instruction is used to load a value from the stack into a register for further processing.
The STR (Store Register) instruction in ARM64 is used to store the value of a register into memory. It is commonly used to save data from a register into a specific memory location.
STR
Rt: The register whose value is to be stored.BaseRegister: The base register that holds the memory address.Offset: The optional offset added to the base address.
// Store the value of x0 into memory at the address in x2
STR x0, [x2]
// Store the value of x0 into memory at the address in x2 with an offset of 16 bytes
STR x0, [x2, #16]
The following C-code demonstrates a scenario that could translate to the use of the STR instruction:
void store_register(uint64_t *memory, uint64_t value) {
memory[0] = value; // Corresponds to storing the value into memory
}
In assembly, this could translate to:
// Assuming x0 = memory, x1 = value
STR x1, [x0]