What do cqto (and the related cdq/cltd) do, and why does signed division need them?
They sign-extend the value in %rax/%eax into the full %rdx:%rax/%edx:%eax pair, building the high half a signed idiv requires.
* cqto sign-extends rax into rdx to build the 128-bit rdx:rax dividend; unsigned div zeroes rdx with xor instead. *
x86 signed division (idivq) divides a double-width dividend held across two registers — %rdx:%rax (128-bit) — by its operand. But your numerator is usually just a 64-bit value in %rax. cqto fills %rdx with copies of %rax's sign bit so the 128-bit value represents the same signed number:
# compute w = y / z, with y in %rsi, z in %rcx
movq %rsi, %rax # dividend low half = y
cqto # sign-extend y into rdx:rax (rdx = all 0s or all 1s)
idivq %rcx # rax = y / z, rdx = y % z
Why you can't skip it: if %rdx held leftover garbage, idiv would interpret a wrong 128-bit dividend and produce nonsense (or a divide exception). cqto makes the high half correct for signed division.
| Mnemonic (AT&T) | Extends | Into |
|---|---|---|
cltq |
%eax (32) |
%rax (64) |
cqto (cqo) |
%rax (64) |
%rdx:%rax (128) |
cltd/cdq |
%eax (32) |
%edx:%eax (64) |
Contrast: unsigned division (div) uses xor %rdx,%rdx to zero the high half instead. So spotting cqto before an idivq tells you the source operands were signed.
Go deeper:
CWD/CDQ/CQO — x86 sign-extend reference — CWD/CDQ/CQO sign-extension reference.
IDIV — x86 signed-divide reference — IDIV, which needs the sign-extended double-width dividend.