Instructions

The x86-64 instruction set is large, but it is organised into a handful of categories. Learn the categories and you can guess what an unfamiliar mnemonic does, and where to look it up.

Instruction Categories

You do not need to memorise hundreds of mnemonics. You need to know which family an instruction belongs to, because the family tells you what operands it accepts and what side effects it has.

FamilyPurposeRepresentative mnemonics
Data movementCopy or convert bit patterns between placesmov, movzx, movsx, lea, xchg
ArithmeticInteger maths and its flagsadd, sub, imul, idiv, inc, dec, neg
Logic & shiftsBit-level manipulationand, or, xor, not, shl, shr, sar
ComparisonSet flags for a later decisioncmp, test
Control flowChange which instruction runs nextjmp, jz/je, call, ret, loop
StackPush and pop from the run-time stackpush, pop, pushfq, popfq
SystemTalk to the kernel or the CPU itselfsyscall, int, cpuid, rdtsc
StringBulk operations with repmovsb, stosb, scasb + rep

The Operand Rules

Whatever the family, the same three constraints apply — they come from how x86-64 encodes instructions, not from the assembler:

  1. At most one memory operand. mov [a], [b] is illegal; go through a register.
  2. Sizes must match. mov eax, rbx is illegal; both sides must be 32 bits, or you use an extension instruction.
  3. The destination cannot be an immediate. Constants are read-only, so mov 5, eax makes no sense.

Where the destination is memory and the source is a constant, the assembler genuinely cannot infer the width, and you must supply it: mov qword [ptr], 0.

Moving Data

mov is the most frequent instruction in compiled code, and it is also the most misused, because it copies bits verbatim — it never converts anything.

    mov  rax, rbx        ; register to register
    mov  eax, 7          ; immediate to register
    mov  [rsp+8], rax    ; register to memory
    mov  rcx, [rsp+8]    ; memory to register

Two rules trip everyone up. First, you cannot move memory to memory — one operand must be a register. Second, both operands must be the same size; shrinking or growing a value needs a dedicated instruction.

Widening Values: movzx and movsx

When a small value must be used as a larger one, the empty high bits need a decision: fill with zeros, or copy the sign bit? That decision is exactly the difference between the two instructions.

    mov  al, 0xFF          ; al = 1111 1111
    movzx eax, al          ; zero-extend  -> eax = 00000000 00000000 00000000 11111111 = 255
    movsx eax, al          ; sign-extend  -> eax = 11111111 11111111 11111111 11111111 = -1

    ; 64-bit sign extension from a 32-bit source needs the 'd' variant:
    movsxd rax, eax        ; note: `movsx rax, eax` does NOT exist

This is the mechanism behind every C type conversion between char, short, and int. Getting it wrong is how a signed value silently becomes a huge positive one.

Other Movement Instructions

    xchg rax, rbx          ; swap two registers in one instruction
    lea  rax, [rbx + 8]    ; compute an address (never reads memory)
    push rax               ; put a value on the stack (rsp -= 8)
    pop  rbx               ; take a value off the stack (rsp += 8)

Logic and Shifts

Bitwise Instructions

These operate bit by bit and never carry: bit n of the result depends only on bit n of the operands.

    and  rax, 0x0F         ; keep the low nibble, clear everything else
    or   rax, 0x80         ; force bit 7 on
    xor  rax, 0xFF         ; invert the low byte
    not  rax               ; invert every bit (one's complement)
    xor  eax, eax          ; FASTEST way to set a register to zero

xor eax, eax deserves special mention. Because the same register is on both sides, the result is always zero regardless of the input, and the CPU recognises this pattern as a dependency-free zeroing idiom.

Shifts and Rotates

    shl  rax, 1            ; shift left 1  -> multiply by 2
    shr  rax, 1            ; shift right 1 -> unsigned divide by 2
    sar  rax, 1            ; arithmetic right shift -> SIGNED divide by 2
    rol  rax, 4            ; rotate left: the bits that fall out return on the right

The count may be a constant or the cl register. Knowing whether your data is signed determines whether you choose shr (fills with 0) or sar (copies the sign bit) — they agree only for non-negative values.

Compare and Test

These two instructions produce no useful result value — they exist to set the flags for a following conditional jump.

    cmp  rax, rbx      ; computes rax - rbx, sets flags, THROWS AWAY the result
                       ; ZF=1 if equal, SF/OF decide "less than" for signed values

    test rax, rax      ; computes rax AND rax, sets flags, discards the result
                       ; ZF=1 only if rax is zero  -> "is this register zero?"

The test reg, reg idiom is worth memorising: it is the cheapest way to ask "is this zero?" or "is the sign bit set?" without changing the value. Compilers emit it constantly.

Conditional Move

A branch can be expensive if the CPU mispredicts it. cmov avoids the branch entirely by moving a value only when a condition holds — no jump, no pipeline flush.

    ; rax = max(rax, rbx)  with no branch at all
    mov  rcx, rax          ; assume rax is the larger one
    cmp  rax, rbx          ; compare
    cmovl rcx, rbx         ; if rax < rbx, take rbx instead
    mov  rax, rcx          ; rax now holds the maximum

cmov is strictly better than a branch when the two outcomes are equally likely; it is worse when the branch is highly predictable, because it always does the extra work.

Summary

  • x86-64 instructions fall into a few families: data movement, arithmetic, logic/shift, comparison, control flow, and system.
  • mov never converts; use movzx to zero-extend and movsx/movsxd to sign-extend.
  • and/or/xor/not work bit by bit; xor reg, reg is the standard idiom for zero.
  • cmp and test set flags without producing a result — they feed conditional jumps.
  • cmov replaces branchy selection when prediction would be unreliable.

Next: Arithmetic — the instructions that actually compute, and the flags they set.