Moving data

Registers, memory operands, immediates, sizes, extension, and the MOV family.

Assembly becomes much less mysterious once you see every instruction as a small transfer between registers, memory, and literal values. This chapter starts with those three places and the register widths that connect them.

One register, several widths

The general-purpose registers are 64 bits wide, but you can address their smaller pieces. rax is the full register, eax is its low 32 bits, ax is the low 16, and al is the low byte. The operand size decides how much data an instruction reads or writes.

Structures make those sizes explicit. Here every field is a 32-bit real4, so the complete vector occupies 12 bytes.

One register, several widths source/main.asm
vector struct
    x real4 ?
    y real4 ?
    z real4 ?
vector ends

Keep in mind: The type next to a field or memory operand is part of the program's contract.

Immediate, register, and memory

mov copies a value; it does not erase the source. A literal such as 33 is an immediate, rcx is a register, and var names memory. MASM writes the destination first and the source second.

xchg is different: it swaps its two operands in one instruction.

Immediate, register, and memory source/chapters/move.asm
    xor rcx, rcx
    xor rdx, rdx
    mov rcx, 33
    mov rdx, rcx
    mov rcx, var
    mov var, rdx
    ; constants
    ; -----------------------------------------------------------------------------
    mov rcx, constval
    mov rdx, constval + 8
    ; exchange data
    ; -----------------------------------------------------------------------------
    xchg rcx, rdx
    xchg rcx, var

Keep in mind: Read mov rdx, rcx as “copy rcx into rdx.”

Keep preserved registers balanced

Windows x64 lets a procedure freely change volatile registers such as rax, rcx, and rdx. A preserved register such as rbx must be restored before returning. The unwind directives describe that stack change to Windows.

Keep preserved registers balanced source/chapters/move.asm
move proc frame
    push rbx
    .pushreg rbx
    .endprolog

Keep in mind: Every push rbx in a procedure needs a matching pop rbx on every return path.

Keep these rules

  • Operand width matters: byte, word, dword, and qword are different operations.
  • MASM uses destination-first syntax.
  • Registers are fast working storage; named variables live in memory.