2

I am learning intelx64 assembly (AT&T)

I saw a question to translate from C code to assembly:

if (a>=0)
    b=0;
else
    b=-1;

where I was given:

movl a,%eax
___________
movl %edx, b

While I can solve this in 2 lines or more I can't think of something to solve it in 1 line, any help or hint?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847

1 Answers1

4

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Sorry but I didn't learn thus not allowed to use cdq, aren't there alternatives? –  Apr 04 '21 at 23:11
  • maybe we can use the fact that value of b is equal to MSB of a repeated? –  Apr 04 '21 at 23:27
  • @daniel: *maybe we can use the fact that value of b is equal to MSB of a repeated?* Yes, that's exactly what `cdq` does, that's why it's the answer. I'm pretty sure it's the only single instruction that does that, which is why 8086 included it in the first place (to set up for `idiv`). The other option would be `mov %eax, %edx` / `sar $31, %edx`. If you haven't learned it yet, learn it now; that's why I linked the manual when I first mentioned it. – Peter Cordes Apr 05 '21 at 00:13
  • One way to get compilers to do this is to ask them to sign-extend int to long long, with `-m32 -mregparm=3` (so the arg arrives in EAX, returned in EDX:EAX) https://godbolt.org/z/bPdhqqGdG – Peter Cordes Apr 05 '21 at 00:17