A Small Set of Words

Assembly looks intimidating mostly because of vocabulary, not difficulty. The whole language is built from a handful of ideas, and once you have names for them the listings stop looking like noise. This lesson defines those words, and it doubles as a glossary you can return to whenever a term trips you up later in the course.

Here is one real listing to point at while we name the parts. It is the add function from the previous lesson, compiled without optimizations so every piece is visible:

add(int, int):
	push	rbp
	mov	rbp, rsp
	mov	DWORD PTR -4[rbp], edi
	mov	DWORD PTR -8[rbp], esi
	mov	edx, DWORD PTR -4[rbp]
	mov	eax, DWORD PTR -8[rbp]
	add	eax, edx
	pop	rbp
	ret

Every term below appears somewhere in those ten lines.

The Anatomy of One Instruction

Before naming each part, here is a single line from that listing taken apart. Every instruction has the same shape: an action, then the things it acts on.

mov   DWORD PTR -4[rbp],   edi
│     │                    └─ source: a register (the value to copy)
│     └─ destination: a memory location (4 bytes below rbp)
└─ mnemonic: the action to perform (mov = copy)

Read it as one sentence: "copy the value in register edi into the memory slot 4 bytes below rbp." The labels in that diagram, mnemonic, destination, source, register, and memory, are exactly the words the rest of this lesson defines, one at a time.

Instruction

An instruction is a single command to the CPU: one small, concrete action. Each line in the body above is one instruction. For example:

add	eax, edx

is one instruction that adds two values. The CPU runs instructions top to bottom, one after another, unless one tells it to jump somewhere else. That is the whole model of a program at this level: a list of tiny instructions, executed in order.

one instruction = one action:

   mov  rbp, rsp     ┐
   add  eax, edx     │  the CPU runs them
   pop  rbp          │  top to bottom
   ret               ┘

Mnemonic

The first word on an instruction line is its mnemonic, the short name for what the instruction does. In the listing the mnemonics are push, mov, add, pop, and ret. They are just abbreviations:

  • mov = move (copy a value)
  • add = add
  • ret = return from the function

You met these in the previous lesson. The mnemonic answers "what action?"; everything after it answers "on what?".

   add      eax, edx
   ▲▲▲
   mnemonic (the action)   the rest = what it acts on

Operand

The things an instruction acts on are its operands, written after the mnemonic and separated by commas. In add eax, edx there are two operands, eax and edx. In ret there are none.

This course uses Intel syntax, where the destination comes first. So add eax, edx means "add edx into eax, leaving the result in eax". Operands come in three flavours, which are the next three terms.

   add   eax,   edx
         └┬┘    └┬┘
        dest   source     Intel: destination first
   result stays in eax    (eax = eax + edx)

Register

A register is a tiny, extremely fast storage slot built directly into the CPU. There is only a small, fixed number of them, and they have fixed names. While the CPU is working on values, it keeps them in registers, not in main memory.

In the listing, rbp, edi, esi, edx, and eax are all registers. You do not need to know what each one is for yet; Chapter 2 introduces them properly. For now, just recognise a register as "a named slot the CPU computes with". Registers are the single most important word in this list: most instructions are shuffling values between registers.

CPU registers — a small, fixed set:
   ┌─────┬─────┬─────┬─────┐
   │ rax │ rbx │ rcx │ rdx │
   │ rsi │ rdi │ rbp │ rsp │
   └─────┴─────┴─────┴─────┘
written with no brackets:  eax, rdi

Memory

Memory (RAM) is the much larger, much slower store outside the CPU. Values that do not fit in the handful of registers, or that need to outlive the current calculation, live in memory.

A memory access is written in square brackets. In the listing, DWORD PTR -4[rbp] is a memory operand: it means "the value in memory at the address 4 bytes below wherever rbp points". The DWORD PTR part says how big the access is (a dword is 4 bytes, the size of an int).

The key distinction to carry forward: eax (no brackets) is a register; [rbp] (brackets) is a location in memory. Spotting brackets is how you tell "working with a value" from "reaching out to memory".

   DWORD PTR  -4[rbp]
   └───┬───┘  └──┬──┘
    how big    which address
   (4 bytes)   (4 below rbp)
   brackets [ ] = a trip to memory

Where Values Live: Registers vs Memory

This split is the one worth picturing. Registers are a tiny set of slots inside the CPU; memory is the vast store outside it, reached only through an address in [ ].

        CPU  (tiny, fast)               MEMORY / RAM  (huge, slower)
   ┌─────────────────────────┐     ┌──────────────────────────────┐
   │ registers:              │     │  address       value         │
   │   rax  rbx  rcx  rdx    │ <─> │  -4[rbp] ...... 42            │
   │   rbp  rsi  rdi  ...    │     │  -8[rbp] ...... 7             │
   │ (a small, fixed set)    │     │  (reached only through [ ])   │
   └─────────────────────────┘     └──────────────────────────────┘
      eax = a register                 [rbp-4] = a memory location

So the first question to ask of any operand is: is it a bare name (a register) or wrapped in brackets (a trip to memory)? Almost everything else builds on that one distinction.

Immediate

An immediate is a literal constant written directly inside an instruction. If the function had been return a + 5, you would see something like:

add	eax, 5

Here 5 is an immediate: not a register, not a memory location, just the number itself baked into the instruction. Immediates are how constants from your source code show up in assembly.

   mov   eax,   5
                ▲
            immediate
   a literal number baked into the instruction

Label

A label is a name for a location, and it always ends with a colon. There are two kinds you will meet:

  • A function label marks where a function begins. add(int, int): is one.
  • A jump-target label marks a spot the code can jump to, such as the top of a loop or the start of an else block. These usually look like .L2:.

A label is not an instruction; it occupies no space of its own. It is just a bookmark so that a call or a jump knows where to go.

   square(int):      <- label (function entry)
       imul edi, edi
       ret
   .L2:              <- label (jump target)
   ends with ":" and is not an instruction

Address

An address is simply a number identifying a location in memory, like a house number on a street. The bracket expression -4[rbp] is a recipe for computing an address. Registers can also hold addresses outright: that is all a pointer is at this level, a register holding the address of something rather than a value.

   memory:  [ ... | 42 | ... ]
                    ▲
              address (a numbered location)
   a pointer = a register holding an address

Putting It Together

Read one line of the listing with the vocabulary in hand:

mov	DWORD PTR -4[rbp], edi
  • mov is the mnemonic: copy.
  • It has two operands.
  • The destination (first, Intel syntax) is DWORD PTR -4[rbp], a memory location at an address 4 bytes below rbp.
  • The source is edi, a register holding the first argument.

So the line reads: "copy the value in register edi into the memory slot 4 bytes below rbp." That is the entire skill of reading assembly, applied to one line. The rest of the course is practising it on bigger listings.

Key Takeaways

  • An instruction is one command; the CPU runs instructions top to bottom.
  • The mnemonic is the instruction's short name (mov, add, ret); operands are what it acts on, destination-first in Intel syntax.
  • A register is a small, fast, named storage slot inside the CPU; most instructions move values between registers.
  • Memory is the larger external store, written in [ ]; brackets are how you spot a memory access versus a register.
  • An immediate is a literal constant baked into an instruction.
  • A label names a location (a function start or a jump target) and ends with :.
  • An address is a numeric location in memory; a pointer is just a register holding one.