Timeline
Timeline
2025-09-28
init
This article introduces the basics of AArch64 assembly language, discusses common ARM registers and instruction classifications in detail, and provides an in-depth explanation of the functional details and practical applications of core instructions such as memory load and store, arithmetic and shift, and bit-field operations.
Common ARM Registers

**
sp(stack pointer) is a special register. ** Features:
- Not
x0~x30- Specifically used forStack Pointer
- Points to the current top of the stack

Instruction Classification:
- Memory Load and Store Instructions
- Multi-byte Memory Load and Store
- Arithmetic and Shift Instructions
- Shift Operations
- Bit manipulation instructions
- Conditional operations
- Branch instructions
- Exclusive memory access instructions
- Memory barrier instructions
- Exception handling instructions
- System register access instructions
Load and store instructions
- LDR
- STR
Exercise 1: ldr instruction


Note: there should be no semicolon between lsl and #3
When extended as lsl, the amount can only be #0 or #3 (as defined by ARM documentation)
Exercise 2: ldr pre-indexed and post-indexed modes


Exercise 3: Pre-indexed and Post-indexed Modes of str


ldr Label (Literal)
ReadPC+labelValue
Exercise 4: ldr Pseudo-instruction


- Instruction: Each instruction corresponds to a CPU operation
- Pseudo-instruction: A command to the compiler, processed by the assembler during source program assembly. It can perform functions such as processor selection, defining program modes, defining data, allocating storage, indicating program end, etc. In short, it can be decomposed into a set of several instructions
- The ldr instruction can be either a large-range address load pseudo-instruction or a memory access instruction. When its second parameter is preceded by ‘=’, it indicates a pseudo-instruction; otherwise, it indicates a memory access instruction
- The ldr pseudo-instruction has no immediate value access restriction
ldr x6, MY_LABEL is a memory access instruction
ldr x7, =MY_LABEL is the ldr pseudo-instruction
Exercise 5: Implementing memcpy in assembly



It can be seen that 0xffffffff was not copied over because the starting address is not 4-byte aligned


mov instruction
- 16-bit immediate

ldp and stp
Provided in the A32 instruction setLDMandSTMto implement multi-byte memory load and store. In the A64 instruction set, LDM and STM instructions are no longer provided; instead, LDP and STP instructions are used
- ldp and stp can load and store 16 bytes with a single instruction

Exercise 6: memset


Exercise 7: pitfalls
Load a very large value into a general-purpose register, e.g., 0xffff_0000_ffff_ffff
Load the value of a register, e.g., the sctrl_el1 register






Note that using ldr may generate a literal pool; it’s better to use the adrp instruction
Store instruction variants
| Instruction | Meaning (Full Name) | Access Size | Sign Extension |
|---|---|---|---|
| LDR | Load Register | 32-bit (W register) or 64-bit (X register) | Unsigned |
| LDRSW | Load Register Signed Word | 32-bit → sign-extend to 64-bit | Signed |
| LDRB | Load Register Byte | 8-bit → zero-extend to 32/64-bit | Unsigned |
| LDRSB | Load Register Signed Byte | 8-bit → sign-extend to 32/64-bit | Signed |
| LDRH | Load Register Halfword | 16-bit → zero-extend to 32/64-bit | Unsigned |
| LDRSH | Load Register Signed Halfword | 16-bit → sign-extend to 32/64-bit | Signed |
| LDRQ | Load Register Quadword (NEON/SIMD register) | 128-bit (V register) | Unsigned |
| STR | Store Register | 32-bit or 64-bit | Unsigned |
| STRB | Store Register Byte | 8-bit | Unsigned |
| STRH | Store Register Halfword | 16-bit | Unsigned |
Supplementary Notes
- Unsigned load (LDR, LDRB, LDRH): High bits filled with zeros
0。 - Signed load (LDRSB, LDRSH, LDRSW): Sign-extended (if the most significant bit is 1, it is extended with 1s).
- If accessing and storing 4 bytes or 8 bytes, both use ldr and str, except that the target register uses wn or xn
STRThe series of instructions does not have a signed version, because when storing, it is written to memory “as is”,without sign extension, zero extension, or any padding operation, but note the register bit width, such as xn and wn are different.- AArch64 defaults to little-endian (low address stores low byte).
- There is also a category ofatomic load/store instructions(
LDAXR、STLXRetc.) used for lock operations
Arithmetic and shift instructions
The four condition code bits NZCV in the pstate processor state

add addition instruction
The ordinary addition instruction add
- Addition using registers
- Addition using immediate values
- Addition using shift operations
adds instruction - affects condition flags (carry)
Mainly affects the C flag (unsigned overflow)
sub subtraction instruction
Ordinary subtraction instruction
subs instruction - affects condition flags (C flag)
adc instruction (add with carry)

sbc instruction (subtract with carry)

Wd = Wn - Wm-1+ C
cmp compare instruction
Compares two numbers, internally implemented using the subs instruction, affects the C flag
Equivalent to
1 | SUBS XZR, <Xn>, #<imm> |
When both x1 and x2 are unsigned numbers
1 | cmp x1, x2 |
x1 - x2 = x1 + ~x2 + 1 (overflow occurs)
When x1 >= x2, C=1
When x1 < x2, C=0
Exercise 1: C condition flag of adds and cmp instructions


| Bit | Name | Meaning |
|---|---|---|
| 31 | N | Result is negative |
| 30 | Z | Result is zero |
| 29 | C | Unsigned comparison no borrow (Carry) |
| 28 | V | Signed overflow |

Exercise 2: cmp and sbc instructions


Shift Operation
- LSL Logical Shift Left
- LSR Logical Shift Right
- ASR Arithmetic Shift Right
- ROR Rotate Right

Bitwise AND Operation
- andAND Operation
- andsAND with Carry, Affects Z Flag
Bitwise OR Operation
- orrOR Operation
- eorXOR Operation

Bit Clear
- bicBit Clear Instruction
Uncommon
Exercise 3: Testing the ANDS Instruction and the Z Flag


Bitfield Insert Operation
Bitfield

bfiBitfield Insert Instruction
bitfield insert

Xd: Destination Register
Xn: Source Register
lsb:Least Significant Bit, i.e.,The index of the lowest bit position in the destination register Xd where insertion begins(counting from 0).
width: The bit width to be inserted (number of bits).

UBFX unsigned bit field extract instruction
SBFX signed bit field extract instruction

Note: counting starts from 0
Exercise 4: Testing bitfield instructions



Multiplication and division instructions
Multiplication:
| Instruction | Function description |
|---|---|
| MADD | Multiply-Add:Xd = (Xn * Xm) + Xa |
| MNEG | Multiply-Negate:Xd = -(Xn * Xm) |
| MSUB | Multiply-Subtract:Xd = Xa - (Xn * Xm) |
| MUL | Multiply:Xd = Xn * Xm(lower 64 bits of result) |
| SMADDL | Signed Multiply-Add Long: 32-bit * 32-bit → 64-bit, plus addend |
| SMNEGL | Signed Multiply-Negate Long: 32-bit * 32-bit → 64-bit, negate |
| SMSUBL | Signed Multiply-Subtract Long: 32-bit * 32-bit → 64-bit, perform subtraction |
| SMULH | Signed Multiply returning High half: take high 64 bits of 128-bit result (signed) |
| SMULL | Signed Multiply Long: 32-bit * 32-bit → 64-bit |
| UMADDL | Unsigned Multiply-Add Long: unsigned version |
| UMNEGL | Unsigned Multiply-Negate Long: unsigned version |
| UMSUBL | Unsigned Multiply-Subtract Long: unsigned version |
| UMULH | Unsigned Multiply returning High half: take high 64 bits (unsigned) |
| UMULL | Unsigned Multiply Long: unsigned 32-bit * 32-bit → 64-bit |
Division:
| Instruction | Function Description |
|---|---|
| SDIV | Signed Divide: signed division |
| UDIV | Unsigned Divide: unsigned division |
Compare and branch instructions
Exercise 5: Using bitfield instructions to read registers

Note that instructions like ubfx can only extract bitfields from general-purpose registers, not directly from system registers. Therefore, you need to first use msr to store the system register into a general-purpose register.
Read system register (move register from system)
1 | mrs x1, ID_AA64ISAR0_EL1 |
Write system register (move system from register)
1 | msr ID_AA64ISAR0_EL1, x1 |
⚠️ But note: many CPU feature registers (such as
ID_AA64ISAR0_EL1) areread-only, soMSRwriting to this register usually triggers an exception and cannot be modified arbitrarily.

Count leading zeros instruction clz
clz: Counts the number of zeros before the highest set bit

Comparison instruction
cmp
Compare two numbers
cmp x1, x2
x1-x2
cmn
Negative comparison
cmn x1, x2
x1+x2
Condition operation suffix
| Condition suffix | Meaning | Flag | Condition code | Abbreviation description |
|---|---|---|---|---|
| EQ | Equal | Z=1 | 0b0000 | Equal |
| NE | Not equal | Z=0 | 0b0001 | Not Equal |
| CS/HS | Unsigned greater than or equal | C=1 | 0b0010 | Carry Set / Higher or Same |
| CC/LO | Unsigned less than | C=0 | 0b0011 | Carry Clear / Lower |
| MI | Negative | N=1 | 0b0100 | Minus |
| PL | Positive or zero | N=0 | 0b0101 | Plus |
| VS | Overflow | V=1 | 0b0110 | Overflow Set |
| VC | No Overflow | V=0 | 0b0111 | Overflow Clear |
| HI | Unsigned Greater Than | (C=1) && (Z=0) | 0b1000 | Higher |
| LS | Unsigned Less Than or Equal | (C=0) ∨ (Z=1) | 0b1001 | Lower or Same |
| GE | Signed Greater Than or Equal | N = V | 0b1010 | Greater or Equal |
| LT | Signed Less Than | N ≠ V | 0b1011 | Less Than |
| GT | Signed Greater Than | (Z=0) && (N=V) | 0b1100 | Greater Than |
| LE | Signed Less Than or Equal | (Z=1) ∨ (N≠V) | 0b1101 | Less or Equal |
| AL | Unconditional Execution | – | 0b1110 | Always |
| NV | Unconditional Execution | – | 0b1111 | Never (Reserved, Generally Not Used) |
Exercise 1: cmp/cmn Instructions and Conditional Operation Suffixes



NZCV register structure diagram

1 | ┌───┬───┬───┬───┐ |
N (Negative flag)
- Result is negative (most significant bit of signed number is 1) → N=1
- Otherwise N=0
Z (Zero flag)
- Result equals 0 → Z=1
- Otherwise Z=0
C (Carry flag)
- Addition: carry occurs → C=1
- Subtraction: no borrow (i.e., operand 1 ≥ operand 2) → C=1
- Otherwise C=0
V (Overflow flag)
- Signed addition/subtraction overflow (result exceeds representable range) → V=1
- Otherwise V=0
Conditional select instruction
Used with the cmp instruction
csel

cset

csinc
Conditional Select Increment

Exercise 2: Conditional select instruction


Branch instruction
b unconditional branch
Branch instruction, unconditional branch instruction, does not return
Branch range: PC +/- 128MB
b.cnd conditional branch instruction
Conditional branch instruction, does not return
cnd is the condition operation suffix
Branch range: PC +/- 1MB
bx branch to address specified by register
Branch to address specified by register, does not return
bl (Branch with Link) branch with return address
With return address (PC+4 => x30), suitable for calling subroutines
The return address is saved to x30, which stores the parent function’s PC+4
Jump range: PC +/- 128MB
blx (Branch with Link to Register)
Jump to the address specified by the register, can return
The return address is saved to x30, which stores the parent function’s PC+4
Return instruction
ret
Return from a subroutine, typically with the return address stored in x30
eret
Return from the current exception mode, typically allowing mode switching, e.g., from EL1 to EL0
It returns from the current exception mode, restoring PSTATE from SPSR, obtaining the jump address from ELR, and returning to that address
Exercise 3: Why does it crash after ret


Traps and pitfalls
bl instruction: used to call a subroutine, it writes the return address to the x30 register, with the return address being PC+4
When calling bl to call a subroutine within a function, it may overwrite the parent function’s lr register, causing the parent function’s ret to crash
Simply put, the subroutine changed the value of the x30 register and did not restore it upon return.
Compare and branch instructions
cbz cbnz tbz tbnz
| Instruction | Abbreviation meaning | Description |
|---|---|---|
| CBZ | Compare and Branch if Zero | Checks if the value of the specified register is zero; if zero, branches to the target address with a range of +/- 1MB. |
| CBNZ | Compare and Branch if Non-Zero | Checks if the value of the specified register is non-zero; if non-zero, branches to the target address with a range of +/- 1MB. |
| TBZ | Test Bit and Branch if Zero | Checks if a specific bit of the specified register is 0; if that bit is 0, branches to the target address with a range of +/- 32KB. |
| TBNZ | Test Bit and Branch if Non-Zero | Checks if a specific bit of the specified register is 1; if that bit is 1, branches to the target address with a range of +/- 32KB. |
Other important instructions
PC-relative address load instruction
- adr instruction, loads the address of a label relative to the PC, with a range of +/- 1MB

- adrp instruction, loads the address of a label relative to the PC; it only loads the 4KB-aligned address of the label, with a range of +/- 4GB


Exercise 1: Testing the ADRP and LDR instructions





What is the difference between ADRP and LDR
Pitfalls and traps:

LDR pseudo-instruction: loads absolute address
ADRP instruction: loads PC-relative address
When link address equals run address
Address loaded by LDR pseudo-instruction equals address loaded by ADRP instruction
- When link address does not equal run address
ldr pseudo-instruction address: loads the link address (also known as virtual address)
adrp instruction: loads the PC value of the current runtime address plus the offset of the label, i.e., the address of the label at runtime (also known as physical memory)
Exercise 2: Pitfalls of adrp and ldr instructions

Exclusive memory load and store instructions
- ldxr instruction
Exclusive memory load instruction, loads the memory address from memory in an exclusive manner into a general-purpose register
- stxr instruction
Exclusive memory store instruction
- ldrx loads memory, but it monitors access to this memory through an exclusive monitor, which marks the memory address as exclusive access, ensuring it is accessed in an exclusive manner

- stxr is a conditional memory store; the memory address previously marked by ldxr is stored in an exclusive manner. Note that the first register is w0


- The ldxr and stxr instructions are typically used in pairs
- The Linux kernel often uses atomic operations, such as atomic_write(),atomic_set_bit()
- The spinlock mechanism can be simply implemented using the ldxr and stxr instructions
Exercise 3: Using the ldxr and stxr instructions


Exception handling instructions
| Instruction | Name | Description |
|---|---|---|
| SVC #imm | System call instruction(Supervisor Call) | The application uses theSVCinstruction to jump from user mode to kernel mode, typically entering EL1 exception level, used to trigger system calls |
| HVC #imm | Virtualization system call instruction(Hypervisor Call) | The host operating system uses theHVCinstruction to enter EL2 from EL1, invoking the hypervisor, used in virtualization support scenarios |
| SMC #imm | Secure Monitor System Call Instruction(Secure Monitor Call) | The host OS or monitor program uses theSMCinstruction to transition from the Non-secure World to the Secure World, typically triggering an EL3 exception, used in the TrustZone security mechanism |
System Register Access Instructions
| Instruction | Description |
|---|---|
| MRS | Read the value of a system register into a general-purpose register (Move Register from System) |
| MSR | Write the value of a general-purpose register to a system register (Move Register to System) |
Memory Barrier Instructions
| Instruction | Full Name | Function | Strength | Example Use |
|---|---|---|---|---|
| DMB | Data Memory Barrier | GuaranteeExecution order of memory access instructions(e.g., read-after-write will not be reordered) | Medium | Shared data communication between multiple cores |
| DSB | Data Synchronization Barrier | Wait for all memory accesses to completebefore executing subsequent instructions | Strong | Cache synchronization before and after reading/writing peripheral registers |
| ISB | Instruction Synchronization Barrier | Clear instruction pipeline and cache, force re-fetching instructions | Special | Force instruction refresh after changing system status registers |
- DMB
Function: Ensures the order of memory accesses without blocking execution.
Example:
1 | str x0, [x1] // Write data |
- DSB
Function: Must wait for all previous memory operations to complete before continuing with subsequent instructions.
Example:
1 | str x0, [x1] // Write data |
- ISB
Function: Clears the CPU instruction prefetch cache, typically used after modifying system control registers.
Example:
1 | msr sctlr_el1, x0 // Modify system control register |
Detailed explanation of DMB/DSB instruction parameters (granularity and scope of memory barriers)
| Parameter | Access order control | Share domain | Description |
|---|---|---|---|
SY | Read/Write | Full System Sharing | Strongest,All processors and devicesVisible, commonly used in device drivers or critical synchronization |
ST | Write | Full System Sharing | Only forWrite operationsEstablish order |
LD | Read | Full System Sharing | Only forRead operationsEstablish order |
ISH | Read/Write | Inner Shareable | Used when multiple cores share the same L2 cache |
ISHST | Write | Inner Shareable | of the inner shareable domainWrite barrier |
ISHLD | Read | Inner Shareable | of the inner shareable domainRead barrier |
NSH | Read/Write | Non-shareable | Used for private memory of this core |
NSHST | Write | Non-shareable | This core private write barrier |
NSHLD | Read | Non-shareable | This core private read barrier |
OSH | Read/Write | Outer Shareable | Used when sharing among multiple L2s |
OSHST | Write | Outer shareable | Outer shareable write barrier |
OSHLT | Read | Outer shareable | Outer shareable read barrier |
Overview Summary
The instruction set running in the aarch64 execution state; 64 refers to its execution environment, not the instruction length.
The instruction length is 32 bits, not 64 bits.
31 general-purpose registers; xn is 64 bits, wn is 32 bits.
Zero registers: xzr, wzr.
PC is not a general-purpose register and generally cannot be directly returned.
x30 is used as the link register (lr) for function return.
ELR_ELx is used for returning from exceptions.
Each exception level has its own stack SP, for example SP._EL0, SP_EL1
SP is not a general-purpose register.
Registers for SIMD and floating-point operations.
Qn (128 bits, 16 bytes), Dn (64 bits), Sn (32 bits), Hn (16 bits), Bn (8 bits).
PSTATE(Processor State Register)It is not a single physical register that exists independently., but rathera collection of processor states composed of multiple bit fields.。PSTATEThe value controls the current state of the CPU, including exception masking, current exception level, condition codes, etc.
| Field | Description |
|---|---|
NZCV | Condition code flags (ALU Flags) used for conditional jumps, etc.:N(Negative),Z(Zero),C(Carry),V(Overflow) |
Q | Overflow flag bit, set only in AArch32 when certain SIMD operations overflow |
DAIF | Exception mask bits:D: Debug exception maskA: SError maskI: IRQ interrupt maskF: FIQ interrupt mask |
SPSel | SP register selection (AArch64 only) controls whether to useSP_EL0orSP_ELx |
CurrentEL | The current exception level (EL0/EL1/EL2/EL3) affects privileged access and execution |
E | Endianness selection (AArch32) controls whether data access is little-endian or big-endian |
IL | When the illegal instruction flag is set to 1,all instructions are executed as UNDEFINED, for debugging |
SS | The single-step execution flag (Software Stepping) is used with the debugger, triggering an exception after each instruction execution |
- Load and store instructions
| Instruction | Type | Data size | Sign extension | Store/Load target |
|---|---|---|---|---|
LDR | Normal load | Per register | No | Any bit width |
LDRSW | Load signed word | 32-bit | ✔ (sign-extend to 64-bit) | Xn only |
LDRB | Load byte | 8-bit | No | Wn/Xn |
LDRSB | Load signed byte | 8-bit | ✔ | Wn or Xn |
LDRH | Load halfword | 16-bit | No | Wn/Xn |
LDRSH | Load signed halfword | 16-bit | ✔ | Wn or Xn |
STRB | Store byte | 8-bit | N/A | — |
STRH | Store halfword | 16-bit | N/A | — |
Instruction suffix meaning
| Suffix | Meaning |
|---|---|
B | Byte(8-bit) |
H | Halfword(16-bit) |
W | Word(32-bit) |
S | Sign-extended |
| No suffix | Default load or store according to target register bit width |
- Multi-byte load and store instructions
- The A64 instruction set has removed ldm, stm, push, and pop instructions
- ldp and stp implement multi-byte load and store instructions
PC-relative instructions
ldr x0, =label(pseudo-instruction)
- Meaning: Load
labelthe address of (link address) tox0。 - Implementation method: The assembler will generate a constant table in the
.rodataarea,ldractually loads the address from the constant table. - Applicable scenario: Can be used anywhere, butdepends on link-time address information, caution is needed in systems that support relocation.
ldr x0, label
- Meaning: Load the value at address
labelintox0. - Note: Here,
labelis an address, and the data it points to will be loaded into the register (not the address itself). - Different from above: This is not a load address, but ratherreading data through the address。
adr x0, .
- Meaning: Load the current PC value into
x0. - Common scenarios: Locate the current code position (e.g., implementing Position-Independent Code).
adrp x0, label
- Meaning: Load the
labelpage where**page start address (4KB aligned)**intox0. - Usage:
- Often used forPosition-Independent Code (PIC)。
- Combined with
addto achieve full address loading:
| Flag | Meaning | Common Triggering Conditions |
|---|---|---|
N | Negative Flag: Set when the result is negative | e.g.,subs x0, x1, x2yields a negative number |
Z | Zero Flag: Set when the result is zero | e.g.,subs x0, x1, x1, result is 0 |
C | Carry Flag: Carry from unsigned addition / borrow from unsigned subtraction | e.g.,adds,subs,adc,sbc |
V | Overflow flag: overflow during signed addition/subtraction | e.g.adds,subsoverflow |
Recommended to consult documentation
arm8.6 Chapter C3 A64 Instruction Set Overview
Traps and pitfalls: runs on QEMU but not on the board
Pitfall 1: ldr instruction loading macro



In bare-metal programming, the MMU is not enabled, so memory attributes are always treated as Device memory
The ldr instruction accesses 8 bytes; if the address is not 8-byte aligned, it triggers an alignment exception, i.e., Data abort
Solution:
1 | ldr x6, MY_LABEL |
Pitfall 2: ldr instruction loading string

This is also caused by alignment, because the starting address of string1 cannot be guaranteed to be 8-byte aligned.
Solution: Align string1 to 8 bytes.

Summary of Aligned Access
- For normal memory, unaligned access is supported. (Requires enabling MMU and setting the memory attribute to normal.)
- You can separately configure an exception to be triggered on unaligned access (by setting SCTLR_Elx.A).
- For Device memory, unaligned access triggers a Data Abort exception.
- In systems without MMU enabled, such as our experimental DDR programming, access is treated as device memory.
- Instruction prefetch requires 4-byte alignment; otherwise, an exception is triggered.
- Normal memory supports unaligned access.
- Condition:
- MMU is enabledMMU(Memory Management Unit);
- and the memory region’s attribute is set toNormal memory;
- Result:
- Supports unaligned access to words (4 bytes), halfwords (2 bytes), and bytes (1 byte).
- Cross-boundary access is possible without triggering an exception;
- Configure unaligned access exception (SCTLR_ELx.A bit)
- SCTLR_EL1.AControls whether to allowunaligned access(Alignment Check):
A = 0(default): Allow unaligned access (if the memory type permits);A = 1:Force aligned access, once an unaligned access occurs, it triggersAlignment fault exception (Data Abort);
- Device memory does not support unaligned access
- Characteristics:
- Regardless of whether the MMU is enabled, the Device memory typedoes not allow unaligned access;
- Consequences:
- Once an unaligned address is accessed (e.g., accessing
0x100332-bit data), it will triggerData Abort exception;
- Once an unaligned address is accessed (e.g., accessing
- Application example:
- Direct-mapped access in experimental environmentDDR, peripheral registers, etc., are typically defined as Device memory type;
- Access to these regions must be aligned; for example, accessing 32-bit data must be 4-byte aligned;
- Instruction prefetch requirements
- Instruction fetch addressmust be4-byte aligned(i.e., the lowest two bits of the address must be 0);
- Otherwise, it triggers anInstruction Abort exception;
- Reason: ARMv8 instructions are stored and fetched in 4-byte units, and cannot be decoded or executed from an unaligned address.
Pitfall 3: Size of stored instruction data
When using the str instruction to set a register, be sure to pay attention to the register’s bit width, otherwise a system crash may occur.
The register bit width on the Raspberry Pi 4b is 32 bits, which is 4 bytes.

Pitfall 4: The big pitfall of ldxr

The use of the ldxr instruction has many restrictions.
- First, ensure that the accessed memory is normal memory and is shareable.

- If accessing device memory, for example when the MMU is not enabled, then the CPU IP core needs to support exclusive access to device memory. This requires consulting the specific CPU IP manual’s description.
For example: Cortex-A72 MPCore Processor Technical Reference Manual, Section 6.45

Solution:
Fill in the page table, enable the MMU and cache, then you can use ldxr and stxr.
Implementing serial port printing functionality in assembly


🧱 1. GPIO Initialization (Pin Multiplexing Configuration)
1 | ldr x1, =GPFSEL1 |
✅ Effect: Set GPIO14 and GPIO15 to UART function (ALT0 mode).
🧱 2. Disable Pull-up/Pull-down (Pi 3B Configuration Only)
1 | #ifdef CONFIG_BOARD_PI3B |
✅ Disable pull-up/pull-down for GPIO14/15, consistent with BCM2837 initialization flow.
🧱 3. UART Initialization
1 | // Disable UART |
✅ Correctly configure baud rate and data format (8N1, FIFO), then enable UART.
You are using:
Baud rate = UARTCLK / (16 * (IBRD + FBRD/64))
Assuming UARTCLK = 48 MHz, the baud rate is approximately 115200.
🧱 4. Single character output function put_uart
1 | put_uart: |
✅ Waits for FIFO to be available before sending the character.
🧱 5. String output function put_string_uart
1 | put_string_uart: |
✅ Input: x0 = string address, print it until NULL (0x00) is encountered.
