Mnemonic
cltq
is the gas
mnemonic for Intel’s cdqe
as documented at: https://sourceware.org/binutils/docs/as/i386_002dMnemonics.html
The mnemonics are:
- Convert Long To Quad (
cltq
): AT&T-style - Convert Double to Quad Extend (
cdqe
): Intel
Terminology:
- quad (aka quad-word) == 8 bytes
- long (AT&T) == double-word (Intel) == 4 bytes
This is one of the few instructions whose GAS name is very different from the Intel version. as
accepts either mnemonic, but Intel-syntax assemblers like NASM may only accept the Intel names.
Effect
It sign extends 4 bytes into 8 bytes, which in 2’s complement means that for:
- negative numbers, the bits of the upper 4 bytes must set to 1
- positive numbers, they must be set to 0
In C, that usually represents a cast from signed int
to long
.
Example:
mov $0x0123456700000001, %rax # eax=1, high bytes of rax=garbage
cltq
# %rax == $0000 0000 0000 0001
mov $-1, %eax # %rax = 0000 0000 FFFF FFFF
cltq
# %rax == $FFFF FFFF FFFF FFFF == qword $-1
This instruction is only available on 64-bits.
Also consider the following instructions:
CWDE
(AT&TCWTL
),CBW
(AT&TCBTW
): smaller versions ofCDQE
, also present in 32-bitCQO
family, which sign extendsRAX
intoRDX:RAX
MOVSX
family, which both sign extends and moves: what does movsbl instruction do?
Minimal runnable examples on GitHub with assertions:
CWDE
andCWTL
CDQE
andCLTQ
C example
GCC 4.9.3 emits it:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int i = strtol(argv[1], (char **)NULL, 16);;
long int l = i;
printf("%lx\n", l);
}
Compile and disassemble:
gcc -ggdb3 -std=c99 -O0 a.c
objdump -S a.out
contains:
int main(int argc, char **argv) {
...
long int l2 = i;
400545: 8b 45 fc mov -0x4(%rbp),%eax
400548: 48 98 cltq
40054a: 48 89 45 f0 mov %rax,-0x10(%rbp)
and the behavior is:
$ ./a.out 0x80000000
ffffffff80000000
$ ./a.out 0x40000000
40000000