A First Look at SIMD

x86-64 Assembly

Chapter 9 · A First Look at SIMD

Every instruction covered since assembly1-1 — across all three courses — has operated on one piece of data at a time. This chapter previews something genuinely different: instructions that operate on several pieces of data at once. Deliberately light-touch, on purpose — this is honestly a topic large enough to be its own course.

Why Vector Instructions Exist — SIMD in One Idea

SIMD — Single Instruction, Multiple Data. Every ordinary instruction this entire arc has covered works on one value: one register, one memory operand. Adding two 4-element arrays together the ordinary way takes four separate ADD instructions, one pair at a time. A SIMD instruction packs several values into one wide register and performs the same operation on all of them simultaneously, inside a single instruction's own execution — not four instructions doing one thing each, but one instruction doing four things at once.

The Real Lineage — MMX → SSE → AVX

ExtensionYearRegistersWidthReal note
MMX1996MM0–MM764-bitPhysically shared the existing x87 floating-point register space — a real, genuinely awkward compromise
SSE1999+XMM0–XMM15128-bitA genuinely separate register set, resolving MMX's own sharing problem
AVX2011+YMM0–YMM15, ZMM (AVX-512)256/512-bitExtends the same register numbering further and wider

MMX's own register-sharing compromise meant a program couldn't freely mix MMX instructions with ordinary floating-point math without real overhead switching between the two uses of the same physical registers. SSE fixed this by giving vector instructions their own dedicated register file entirely. This whole lineage is one more concrete instance of assembly2-1's own "four decades of accretion" theme — SIMD has its own internal history of layered extensions, each one adding capability on top of the last, mirroring assembly2-2's own RAX/EAX/AX nesting, just for an entirely different feature.

One Worked Example

Adding two 4-element arrays of single-precision floats, the SIMD way:

MOVUPS XMM0, [array1]   ; load 4 floats from array1 into XMM0
MOVUPS XMM1, [array2]   ; load 4 floats from array2 into XMM1
ADDPS  XMM0, XMM1       ; add all 4 pairs simultaneously — ONE instruction
MOVUPS [result], XMM0   ; store all 4 results back at once

ADDPSADD Packed Single-precision — the mnemonic itself describes exactly what it does. The equivalent ordinary, scalar version of this same task would need four separate ADD-family instructions, one value pair at a time; ADDPS does all four in one.

Not every CPU supports every extension
A real program can't just assume AVX-512, or even AVX, is available — SIMD support varies by CPU model and generation. Real code checks which extensions the running CPU actually supports (via the CPUID instruction) before using anything beyond the most basic, universally-present SSE instructions. Using an unsupported instruction doesn't degrade gracefully; it faults.

Honestly Scoping This Topic

This is genuinely as far as this course goes. A real, complete treatment of SIMD would need to cover the many packed integer/float data-type variants, each instruction set's own feature-detection requirements, real memory-alignment rules (some SIMD instructions fault on unaligned memory operands), and AVX-512's own further masking and broadcasting capabilities. All of that is large enough to be a genuinely separate course on its own — this chapter deliberately stops here rather than pretending a shallow tour is complete coverage.

A big share of assembly2-7's own instruction count
assembly2-7 already named SIMD extensions as a major reason x86-64's own honest instruction count runs into the thousands rather than the hundreds — this chapter is the concrete look at exactly which family of instructions is doing most of that counting.

Hands-On Exercises

Exercise 1

Using this chapter's own ADDPS example, explain what "packed" means in this context, and explain specifically why one ADDPS instruction accomplishes what would otherwise take four separate scalar ADD instructions.

📄 View solution
Exercise 2

Explain the real historical MMX register-sharing problem described in this chapter, and explain specifically why SSE's own separate XMM register set was a genuine improvement rather than just a wider version of the same idea.

📄 View solution
Exercise 3

List at least two specific things this chapter names as out of scope, and explain why the chapter treats naming them explicitly as more honest than simply not mentioning them at all.

📄 View solution

Chapter 9 Quick Reference

  • SIMD — Single Instruction, Multiple Data: one instruction operates on several packed values at once
  • MMX (1996) — shared registers with the x87 FPU, a real design compromise
  • SSE (1999+) — a genuinely separate 128-bit XMM register file
  • AVX (2011+) — extends the same registers to 256-bit (YMM) and 512-bit (ZMM, AVX-512)
  • ADDPS — ADD Packed Single-precision — adds 4 float pairs in one instruction instead of 4 separate ADDs
  • Real programs must check CPU support (via CPUID) before using advanced SIMD extensions — nothing degrades gracefully
  • Deliberately scoped light — data type variants, alignment rules, and AVX-512 masking/broadcasting are all honestly out of scope