Skip to content

Assembly SSE — SIMD Vector Instructions for Parallel Processing

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Assembly SSE. We cover key concepts, practical examples, and best practices to help you master this topic.

SSE (Streaming SIMD Extensions) provides packed single and double precision operations on 128-bit XMM registers for parallel data processing over 2-4 elements at once.

What You'll Learn

  • XMM register layout (128-bit)
  • Packed arithmetic instructions
  • Shuffle and blend operations
  • SSE vs scalar performance

Why It Matters

SSE operations Process 4 floats or 2 doubles in one instruction. Doda Browser uses SSE for accelerated CSS animation calculations and image processing filters.

Real-World Use

Image processing (pixel manipulation), audio processing (sample mixing), video encoding (motion estimation), physics simulation (particle systems), and cryptography (AES-NI).

flowchart LR
    A["XMM Register"] --> B["4 x 32-bit Float"]
    A --> C["2 x 64-bit Double"]
    A --> D["16 x 8-bit Byte"]
    A --> E["8 x 16-bit Word"]
    B --> F["addps, mulps"]
    C --> G["addpd, mulpd"]
    D --> H["paddb"]
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#dbeafe,stroke:#2563eb,color:#1e40af

XMM Register Layout

XMM0: [  float3  |  float2  |  float1  |  float0  ]  128 bits
         bit127              bit63               bit0

XMM0: [     double1      |      double0      ]  128 bits

16 XMM registers in 64-bit mode (XMM0-XMM15).

Packed Float Addition

section .data
    a dd 1.0, 2.0, 3.0, 4.0
    b dd 5.0, 6.0, 7.0, 8.0
    result dd 0.0, 0.0, 0.0, 0.0

section .text
    movaps xmm0, [a]        ; load aligned packed floats
    movaps xmm1, [b]
    addps xmm0, xmm1        ; packed add
    movaps [result], xmm0

    ; result = [6.0, 8.0, 10.0, 12.0]

Packed Double Addition

section .data
    a dq 1.0, 2.0
    b dq 3.0, 4.0
    result dq 0.0, 0.0

section .text
    movapd xmm0, [a]        ; load aligned packed doubles
    movapd xmm1, [b]
    addpd xmm0, xmm1        ; packed double add
    movapd [result], xmm0

    ; result = [4.0, 6.0]

SSE Arithmetic Instructions

; Single precision
addps   ; packed add
subps   ; packed subtract
mulps   ; packed multiply
divps   ; packed divide
sqrtps  ; packed square root

; Double precision
addpd   ; packed add
subpd   ; packed subtract
mulpd   ; packed multiply
divpd   ; packed divide
sqrtpd  ; packed square root

; Horizontal operations
haddps  ; horizontal add (pairwise)
hsubps  ; horizontal subtract

Dot Product Example

section .data
    vec1 dd 1.0, 2.0, 3.0, 4.0
    vec2 dd 5.0, 6.0, 7.0, 8.0

section .text
    movaps xmm0, [vec1]
    movaps xmm1, [vec2]
    mulps xmm0, xmm1        ; [5, 12, 21, 32]
    haddps xmm0, xmm0       ; [17, 53, 17, 53]
    haddps xmm0, xmm0       ; [70, 70, 70, 70]
    ; xmm0[0] = 70 = 1*5 + 2*6 + 3*7 + 4*8

Data Movement

movaps  ; move aligned packed single (16-byte aligned)
movups  ; move unaligned packed single
movapd  ; move aligned packed double
movupd  ; move unaligned packed double
movhlps ; move high to low
movlhps ; move low to high
movshdup ; shuffle odd float elements
movsldup ; shuffle even float elements

Shuffle and Blend

section .data
    a dd 1.0, 2.0, 3.0, 4.0
    b dd 5.0, 6.0, 7.0, 8.0

section .text
    movaps xmm0, [a]
    movaps xmm1, [b]

    ; shuffle: select from a,b based on immediate byte
    ; shufps dest, src, imm8
    ; imm8 encodes 4 selections: dest[0..3] from {dest, src}[0..3]
    shufps xmm0, xmm1, 0xE4
    ; xmm0 = [1.0, 2.0, 7.0, 8.0]

    ; blend: select element-by-element
    ; blendps dest, src, imm8
    ; imm8 bit n = 1 selects from src, 0 from dest
    blendps xmm0, xmm1, 0b1010

Integer SSE Instructions

section .data
    byte_a db 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
    byte_b db 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1

section .text
    movdqu xmm0, [byte_a]   ; load 16 bytes
    movdqu xmm1, [byte_b]
    paddb xmm0, xmm1        ; packed byte add (16 at once)

    ; Other integer ops
    paddw   ; packed word add
    paddd   ; packed dword add
    paddq   ; packed qword add
    psubb   ; packed byte subtract
    pmullw  ; packed word multiply

Comparison and Min/Max

section .data
    a dd 1.0, 5.0, 3.0, 8.0
    b dd 4.0, 2.0, 6.0, 7.0

section .text
    movaps xmm0, [a]
    movaps xmm1, [b]

    cmpps xmm0, xmm1, 0     ; 0=CMP_EQ, 1=CMP_LT, 2=CMP_LE
    ; result mask: all 1s or all 0s per element

    ; Min/max
    minps xmm0, xmm1        ; element-wise minimum
    maxps xmm0, xmm1        ; element-wise maximum

Common Mistakes

1. Alignment faults with movaps

movaps requires 16-byte alignment. Use movups for unaligned data or align your data sections.

2. Mixing packed and scalar instructions

addps uses all 4 elements. addss uses only element 0. Mixing them gives wrong results.

3. Forgetting the shuffle immediate encoding

The 8-bit immediate in shufps encodes element selection positionally. Memorize the pattern or use NASM macros.

4. Not clearing XMM registers before use

SSE divides by zero or compares with stale data produce undefined results. Use xorps xmm0, xmm0 to zero.

5. Ignoring SSE version requirements

SSE (original), SSE2 (double support), SSE3 (horizontal ops), SSSE3, SSE4.1, SSE4.2. Check CPU support via CPUID.

Practice Questions

1. How many floats can one SSE instruction process?

4 single-precision floats in one 128-bit XMM register.

2. What is the difference between movaps and movups?

movaps requires 16-byte aligned memory (faster). movups works with any alignment (slightly slower).

3. How do you compute a dot product using SSE?

Multiply element-wise with mulps, then use haddps twice to sum all elements.

4. What does shufps do?

Shuffles elements between two XMM registers based on an 8-bit immediate control byte.

Challenge: Write an SSE function that computes the sum of squared differences between two float arrays.

Solution
; float ssd(float* a, float* b, int n)
; a in RDI, b in RSI, n in RDX
ssd:
    xorps xmm0, xmm0       ; accumulator
    xor rcx, rcx

.loop:
    movups xmm1, [rdi + rcx * 4]
    movups xmm2, [rsi + rcx * 4]
    subps xmm1, xmm2        ; diff
    mulps xmm1, xmm1        ; square
    addps xmm0, xmm1        ; accumulate
    inc rcx
    cmp rcx, rdx
    jl .loop

    ; Horizontal sum
    haddps xmm0, xmm0
    haddps xmm0, xmm0
    ret

FAQ

{{< faq question="Is SSE available on all x86-64 CPUs?" >}} Yes, SSE2 is mandatory for x86-64. SSE4.2 is available on most modern CPUs (Intel Nehalem+, AMD Bulldozer+). {{< /faq >}}

{{< faq question="What is the difference between SSE and AVX?" >}} SSE uses 128-bit registers. AVX extends to 256-bit and uses 3-operand syntax (dest, src1, src2). {{< /faq >}}

{{< faq question="How do I check if a CPU supports SSE4.2?" >}} Use the CPUID instruction with EAX=1, check bit 20 of ECX for SSE4.2 support. {{< /faq >}}

{{< faq question="Can SSE instructions access memory directly?" >}} Yes, many SSE instructions have memory operand variants: addps xmm0, [mem] loads from memory and adds. {{< /faq >}}

{{< faq question="What is the penalty for misaligned SSE access?" >}} On older CPUs, movups with misaligned data is slower (crossing cache line boundary). On modern CPUs, the penalty is minimal. {{< /faq >}}

Mini Project

Write an SSE-based array magnitude computation.

section .data
    array dd 3.0, 4.0, 5.0, 12.0
    n dd 4

section .bss
    magnitudes resd 4

section .text
    global _start

_start:
    movaps xmm0, [array]
    mulps xmm0, xmm0        ; squares
    sqrtps xmm0, xmm0       ; square roots
    movaps [magnitudes], xmm0

    ; magnitudes = [3.0, 4.0, 5.0, 12.0]
    mov rax, 60
    xor rdi, rdi
    syscall

What's Next

Now that you understand SSE, proceed to AVX (Advanced Vector Extensions).

Topic Description Link
AVX 256-bit SIMD vectors {{< ref "17-avx" >}}
Floating-point Scalar FP operations {{< ref "15-floating-point" >}}
Instructions CPU instruction set {{< ref "06-instructions" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro