Skip to content

Instructions

x86-64

MOVZX / MOVSX / MOVSXD

Zero-extending and sign-extending moves that widen a smaller source operand into a larger destination — essential for understanding type promotions in decompiler output.

MOVZX (Move with Zero-Extension) and MOVSX (Move with Sign-Extension) copy a narrower source into a wider destination, filling the upper bits with zeros or with copies of the source's sign bit respectively. Neither modifies EFLAGS.

Syntax

asm
movzx eax, bl          ; eax = zero_extend(BL)   → upper 3 bytes cleared
movzx eax, word [rdi]  ; eax = zero_extend(u16 from memory)
movzx rax, al          ; rax = zero_extend(AL)   → zero-extends to 64 bits

movsx eax, bl          ; eax = sign_extend(BL)   → 0xFF if BL=0xFF (-1 signed)
movsx rax, eax         ; rax = sign_extend(EAX)  → same as MOVSXD
movsxd rax, edi        ; rax = sign_extend(32-bit EDI) → 64-bit

Zero-extend vs sign-extend

c
// Source C
uint8_t u = 0xC0;   // 192
int8_t  s = 0xC0;   // -64

// Assembly for widening to int
movzx eax, al   // eax = 0x000000C0 = 192 (unsigned)
movsx eax, al   // eax = 0xFFFFFFC0 = -64 (signed)

MOVSXD

MOVSXD sign-extends a 32-bit source into a 64-bit destination — the most common form is movsxd rax, eax (canonicalise a 32-bit result to 64-bit signed). Note: mov eax, eax zero-extends, while movsxd rax, eax sign-extends.

Reverse-engineering notes

  • The presence of movsx tells you the compiler treats the source as a signed type; movzx means unsigned. This directly informs variable type recovery in decompilers.
  • movzx eax, byte [rdi + rcx] is the canonical array byte-read pattern.
  • On x86-64, any 32-bit write implicitly zero-extends to 64 bits, so movzx eax, al and mov eax, eax (after setting AL) are equivalent — decompilers sometimes emit the latter.
  • movsxd is common when a 32-bit loop index is used as a 64-bit pointer offset: movsxd rcx, ecx then mov [rbx + rcx*8], rax.