Lesson 3 of 10
Registers & Data Movement
You'll learn `mov`, the most common instruction, which copies data between registers and (the source is left unchanged). Nearly every program you write will use it.
section .text
global _start
_start:
; mov dst, src — copies src into dst (src unchanged)
; Register to register
mov rax, 42 ; rax = 42
mov rbx, rax ; rbx = 42, rax still 42
; Immediate (literal) to register
mov rcx, 0xFF ; rcx = 255
mov rdx, 0b1010 ; rdx = 10 (binary literal)
mov rsi, 'A' ; rsi = 65 (ASCII for 'A')
; Memory to register (load)
; Square brackets = "the value at this address"
mov rax, [some_var] ; rax = value stored at some_var
; Register to memory (store)
mov [some_var], rbx ; store rbx at address some_var
; Immediate to memory — must specify size
mov qword [some_var], 99 ; store 64-bit value 99
mov dword [some_var], 99 ; store 32-bit value 99
mov word [some_var], 99 ; store 16-bit value 99
mov byte [some_var], 99 ; store 8-bit value 99
; Address arithmetic in brackets
mov rax, [rbp - 8] ; load from rbp minus 8 bytes
mov rax, [rdi + rcx*8] ; load from rdi + rcx*8 (array indexing!)
; lea — load effective address (compute address, don't dereference)
lea rax, [rbp - 8] ; rax = rbp - 8 (the address, not the value)
lea rdi, [rel msg] ; rdi = address of msg (position-independent)
mov rax, 60
xor rdi, rdi
syscall
section .data
some_var dq 0 ; dq = define quadword (8 bytes), initialized to 0
msg db "hi", 0; Size specifiers and their meanings:
; byte — 8 bits (1 byte) — db, al, bl, cl...
; word — 16 bits (2 bytes) — dw, ax, bx, cx...
; dword — 32 bits (4 bytes) — dd, eax, ebx...
; qword — 64 bits (8 bytes) — dq, rax, rbx...
; IMPORTANT: writing to a 32-bit register (eax) zero-extends to 64-bit (rax)
; but writing to 8-bit or 16-bit does NOT zero the upper bits!
mov rax, 0xFFFFFFFFFFFFFFFF
mov al, 0x00 ; rax = 0xFFFFFFFFFFFFFF00 (upper bytes unchanged!)
mov eax, 0x00 ; rax = 0x0000000000000000 (zero-extended!)
; xchg — swap two registers (no temp needed)
xchg rax, rbx
; movzx — move with zero extension
movzx rax, byte [some_byte] ; load 1 byte into rax, zero-fill upper 56 bits
; movsx — move with sign extension (preserves sign bit)
movsx rax, byte [some_signed] ; e.g., -1 (0xFF) becomes 0xFFFFFFFFFFFFFFFFFinished reading?Mark it done to track your progress.
Tip: use the ← and → keys to move between lessons.