Quiz Entry - updated: 2026.07.14
What is sign extension and when is it needed?
Sign extension widens a smaller signed value into a larger register by copying its sign bit, so a negative number stays negative.
* movs copies the top bit to preserve a signed value (0xFF becomes -1); movz pads with zeros for an unsigned value (0xFF becomes 255). *
When you assign a char to an int, the 8 bits must become 32 — but simply padding with zeros would turn −1 (0xFF) into 255. Sign extension instead replicates the top (sign) bit across the new bits, preserving the value's meaning.
char c = -1; // 0xFF
int i = c; // must become 0xFFFFFFFF (still -1), not 0x000000FF (255)
The movs family does this, named by source-and-destination size:
| Instruction | Operation |
|---|---|
movsbq %al, %rax |
sign-extend byte → quad |
movswq %ax, %rax |
sign-extend word → quad |
movslq %eax, %rax |
sign-extend long → quad |
cltq |
sign-extend %eax → %rax (no operands) |
movb $0xFF, %al # -1 as a signed byte
movsbq %al, %rax # %rax = 0xFFFF...FF (-1, sign-extended)
movzbq %al, %rax # %rax = 0x0000...FF (255, zero-extended)
The choice is dictated by signedness: signed source → movs, unsigned source → movz.
Go deeper:
Sign extension (Wikipedia) — preserving sign and value when widening, vs zero-fill.
Felix Cloutier — MOVSX/MOVSXD — the movs-family instruction reference for sign-extension.