Skip to content

Assembly AVX — Advanced Vector Extensions for 256-bit SIMD

DodaTech Updated 2026-06-28 6 min read

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

AVX extends SSE to 256-bit YMM registers with non-destructive 3-operand syntax, enabling 8 single-precision or 4 double-precision operations per instruction.

What You'll Learn

  • YMM registers (256-bit)
  • AVX 3-operand syntax
  • VEX prefix encoding
  • AVX2 integer operations
  • AVX-512 overview

Why It Matters

AVX doubles SSE's throughput and adds non-destructive operations. Doda Browser uses AVX for accelerated image decoding and CSS filter effects in its Rendering Pipeline.

Real-World Use

High-performance computing, video encoding/decoding, Machine Learning inference, scientific simulations, and any workload with regular data-parallel patterns.

flowchart LR
    A["AVX"] --> B["YMM 256-bit"]
    A --> C["3-Operand"]
    A --> D["VEX Prefix"]
    B --> E["8 x Float"]
    B --> F["4 x Double"]
    C --> G["dest, src1, src2"]
    D --> H["No SSE penalty"]
    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

YMM Register Layout

YMM0: [  f7 |  f6 |  f5 |  f4 |  f3 |  f2 |  f1 |  f0  ]  floats
YMM0: [      d3      |      d2      |      d1      |      d0      ]  doubles
       bit255                                                      bit0

16 YMM registers in 64-bit mode (YMM0-YMM15). The lower half of each YMM register is the corresponding XMM register.

Basic AVX Operations

section .data
    a dd 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0
    b dd 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
    result dd 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

section .text
    vmovaps ymm0, [a]       ; load 8 floats
    vmovaps ymm1, [b]
    vaddps ymm2, ymm0, ymm1 ; ymm2 = ymm0 + ymm1 (non-destructive)
    vmovaps [result], ymm2

    ; result = [10, 12, 14, 16, 18, 20, 22, 24]

3-Operand Syntax

; AVX: dest, src1, src2  (src1 and src2 are preserved)
vaddps ymm2, ymm0, ymm1    ; ymm2 = ymm0 + ymm1

; SSE: dest, src  (dest is overwritten)
addps xmm0, xmm1            ; xmm0 += xmm1

; The non-destructive syntax reduces register pressure

AVX Arithmetic

vmovaps   ; move aligned packed single
vmovups   ; move unaligned packed single
vaddps    ; packed add (float)
vsubps    ; packed subtract (float)
vmulps    ; packed multiply (float)
vdivps    ; packed divide (float)
vsqrtps   ; packed square root

vaddpd    ; packed add (double)
vsubpd    ; packed subtract (double)
vmulpd    ; packed multiply (double)
vdivpd    ; packed divide (double)

vhaddps   ; horizontal add (float)
vhsubps   ; horizontal subtract

AVX Fused Multiply-Add

; FMA3 — fused multiply-add (Haswell+)
; dest = src1 * src2 + src3

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

section .text
    vmovaps xmm0, [a]
    vmovaps xmm1, [b]
    vmovaps xmm2, [c]

    vfmadd132ps xmm0, xmm2, xmm1   ; xmm0 = xmm0*xmm1 + xmm2
    vfmadd213ps xmm0, xmm1, xmm2   ; xmm0 = xmm0*xmm1 + xmm2
    vfmadd231ps xmm0, xmm1, xmm2   ; xmm0 = xmm1*xmm2 + xmm0

AVX2 Integer Operations

AVX2 extends integer SIMD to 256-bit:

section .data
    a db 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
      db 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32

section .text
    vmovdqu ymm0, [a]       ; 32 bytes
    vpaddb ymm1, ymm0, ymm0 ; double all bytes
    vpshufb ymm1, ymm0, ymm2 ; shuffle bytes

    ; Gather (AVX2)
    ; vpgatherdd — gather dwords from memory
    mov rax, array_base
    vpgatherdd xmm0, [rax + xmm1 * 4], xmm2

AVX-512 Overview

; AVX-512 extends to 512-bit ZMM registers (32 registers)
; 16 single-precision or 8 double-precision per instruction

; Mask registers (k0-k7) for predication
; Opmask conditional operations

; Example (AVX-512F)
; vaddps zmm0, zmm1, zmm2         ; 16 floats at once
; vaddpd zmm0 {k1}, zmm1, zmm2    ; masked operation

; Requires: Skylake-X (consumer) or Xeon Phi (Knight's Landing)

VEX Prefix Advantages

; SSE: 2-operand, overwrites source
addps xmm0, xmm1            ; xmm0 += xmm1

; AVX: 3-operand, preserves both sources
vaddps xmm2, xmm0, xmm1     ; xmm2 = xmm0 + xmm1

; Benefits:
; + Fewer register copies (less register pressure)
; + Cleaner code
; + No false dependencies (partial register stalls)
; + Can zero registers with vxorps (no dependency)

Memory Alignment

section .data
    ; Align data for AVX
    align 32
    a dd 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0

section .text
    ; vmovaps requires 32-byte alignment
    vmovaps ymm0, [a]       ; aligned load (fast)

    ; vmovups for unaligned
    vmovups ymm0, [rsi + rcx * 4]  ; unaligned (may be slower)

Common Mistakes

1. Mixing AVX and SSE instructions

Transitioning between SSE and AVX has a performance penalty (state change). Use AVX throughout hot code.

2. Forgetting VEX prefix

Modern assemblers auto-prefix AVX instructions. Writing SSE opcodes with YMM registers is invalid.

3. Alignment with vmovaps

vmovaps requires 32-byte alignment. vmovups works with any alignment. Use align 32 in data sections.

4. Not checking AVX support

Older CPUs (pre-Sandy Bridge) lack AVX. Use CPUID to detect. Most x86-64 CPUs from 2011+ have AVX.

5. YMM register save/restore overhead

Context switches save/restore YMM state. Heavy AVX use can cause system-wide slowdown (AVX frequency scaling).

Practice Questions

1. What is the width of a YMM register?

256 bits (compared to 128 bits for XMM).

2. What advantage does AVX's 3-operand syntax provide?

Non-destructive operations preserve source operands, reducing register pressure and eliminating unnecessary copies.

3. How many floats can one AVX instruction Process?

8 single-precision floats per instruction.

4. What is AVX-512?

An extension to 512-bit ZMM registers with 32 registers and mask-based predication for conditional operations.

Challenge: Write an AVX function that computes the element-wise maximum of two 256-bit float vectors.

Solution
; void max_vectors(float* a, float* b, float* out)
; a in RDI, b in RSI, out in RDX
max_vectors:
    vmovaps ymm0, [rdi]
    vmovaps ymm1, [rsi]
    vmaxps ymm2, ymm0, ymm1
    vmovaps [rdx], ymm2
    vzeroupper                  ; clear upper YMM state
    ret

FAQ

{{< faq question="Do all x86-64 CPUs support AVX?" >}} No. Intel Sandy Bridge (2011) and AMD Bulldozer (2011) added AVX. Older CPUs lack it. Check with CPUID before using. {{< /faq >}}

{{< faq question="What is the performance penalty of mixing SSE and AVX?" >> Transitioning from SSE to AVX causes a ~50-cycle state change penalty. Avoid mixing in hot code or use vzeroupper to clear state. {{< /faq >}}

{{< faq question="What is AVX frequency scaling?" >}} Heavy 256-bit/512-bit instructions consume more power, causing the CPU to downclock. AVX-512 has the most aggressive scaling. {{< /faq >}}

{{< faq question="Can I use AVX on 32-bit x86?" >}} Yes, AVX works on 32-bit x86 with OS support (OSXSAVE feature bit). However, 32-bit has only 8 YMM registers. {{< /faq >}}

{{< faq question="What is vzeroupper?" >}} An instruction that zeros the upper 128 bits of all YMM registers, avoiding SSE/AVX transition penalties. {{< /faq >}}

Mini Project

Write an AVX function that computes the element-wise sum of two 8-float arrays.

section .data
    align 32
    a dd 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0
    b dd 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0

section .bss
    align 32
    result resd 8

section .text
    global _start

_start:
    vmovaps ymm0, [a]
    vmovaps ymm1, [b]
    vaddps ymm2, ymm0, ymm1
    vmovaps [result], ymm2

    ; result = [10, 12, 14, 16, 18, 20, 22, 24]
    vzeroupper
    mov rax, 60
    xor rdi, rdi
    syscall

What's Next

Now that you understand AVX, proceed to multi-file assembly projects.

Topic Description Link
Multifile Multi-file projects {{< ref "18-multifile" >}}
SSE 128-bit SIMD {{< ref "16-sse" >}}
Floating-point Scalar FP {{< ref "15-floating-point" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro