Registers & Data Processing
add, sub, mul, division, building constants, and 32- vs 64-bit operations.
Data-processing instructions read one or two source registers (or a small constant) and write a destination register: add x3, x0, x1 means x3 = x0 + x1. From here on, examples are assembly functions called from a small C program that prints the results — exactly how assembly is used in real projects.
Arithmetic
The function's arguments arrive in x0, x1, x2 and the result is returned in x0 (the calling convention, later lesson).
sdiv is signed division; there is no remainder instruction, so msub computes a - (a/b)*b.
stp stores two registers to consecutive memory locations in one instruction.
movz loads a 16-bit chunk and zeroes the rest; movk inserts further 16-bit chunks — needed because an instruction cannot hold a 64-bit constant.
add w0, w0, w1 works on 32 bits and wraps around at 2^32.
Reading the output
mov x0, #0x12345678 movz x0, #0x5678 movk x0, #0x1234, lsl #16 // or: ldr x0, =0x12345678 mov only accepts constants that can be encoded in one instruction. Larger values need movz/movk or the ldr = pseudo-instruction, which loads from a nearby literal pool.
How would you compute a % b in AArch64 assembly?
sdiv x2, x0, x1 (quotient) then msub x0, x2, x1, x0, which gives x0 - x2*x1.