cdq
copies the sign-bit of EAX into all bits of EDX.
Having its sign bit set is equivalent to EAX being less-than zero.
-1
is all-bits-set in a 2's complement machine like x86.
Another way to describe cdq
is sign-extending EAX into EDX:EAX.
The AT&T mnemonic for it is cltd
, very easy to confuse with cltq
, so I recommend just using the Intel mnemonics for those instructions (cdq
vs. cdqe
, where the E for "Extend" is a reminder that it's within one register, into RAX.)
In general, you can try asking a compiler to see if you can get them to use a single instruction for something, or look at the instructions they generate.
Or use a superoptimizer which is software that brute-force tries possible instruction sequences to find the best / shortest one to produce a given result, for a given set of inputs. (Only viable for very short sequences, like a handful of instructions.)
By hand / by eye, you can see that mov
doesn't set FLAGS according to the value, so that rules out any instructions like cmov
. And there aren't any instructions that branch based on EAX (unlike loop
for RCX), and you don't want that anyway. For me, the solution came to mind as soon as I saw it was storing EDX into b
. The combination of EAX and EDX, along with needing a 0
or -1
, reminded me of cdq
.