2

Consider multiplying two signed variables with the value -1 using imulq.

The manual states: "The CF and OF flags are set when the signed integer value of the intermediate product differs from the sign extended operand-size-truncated product, otherwise the CF and OF flags are cleared."

Now, the binary 2's complement representation of -1 is the all-ones string, so (-1)*(-1) would yield a string that looks like (1...10 0...01), so the sign exension of the truncated result differs from the full one.

Does that mean that the OF flag will be set? This is really confusing, becuase intuitively there's no real overflow here.

M A
  • 209
  • 2
  • 7
  • 2
    "(-1)*(-1) would yield a string that looks like (1...10 0...01)", maybe if it was an unsigned multiply that would be true, but imulq is explicitly signed, so the result is 1 even before truncation. – hobbs May 21 '22 at 07:08
  • @hobbs - it's signed, but my understanding is that it performs the same operation as unsigned multiplication, except for the flag handling. – M A May 21 '22 at 07:29
  • @hobbs - (just by looking at answers like in here: https://softwareengineering.stackexchange.com/questions/358173/can-unsigned-and-signed-twos-complement-multiplication-be-performed-on-the-sa#:~:text=is%20not%20useful-,Show%20activity%20on%20this%20post.,the%20same%20(ignoring%20flags).) "As far as hardware goes, unsigned multiplication and signed multiplication are exactly the same (ignoring flags)." Am I mis-interpreting this? – M A May 21 '22 at 07:36
  • Did you try it on a real CPU to confirm your understanding of the manual, and that you got the numbers right? It's pretty trivial to `mov rax, -1` / `imul rax` (or the AT&T equivalent) and single-step it with GDB. On my CPU, OF=0 as expected, because RDX:RAX == sign_extend(RAX). I.e. running `cqo` wouldn't change RDX. RDX=0, RAX=1 – Peter Cordes May 21 '22 at 14:06
  • The link you commented it only talking about low-half non-widening multiplication, which is all most languages give you access to. It's not true for the high half, which is why `mul` and `imul` both have one-operand forms, but only `imul` has `r,r/m` and `r, r/m, imm` forms. – Peter Cordes May 21 '22 at 14:09
  • I closed this as a duplicate because the real problem here is wrong calculation of the product. It's `0:1` in `rdx:rax`, that's why `mul` and `imul` exist separately for the one-operand forms, because their high-half differs, not just FLAGS. I could have written that as an answer here, or someone else could; I can reopen if anyone wants. – Peter Cordes May 21 '22 at 14:33

0 Answers0