assemblyx86eflags

Problem in understanding the overflow flag (OF) as defined by the IMUL instruction


I've confusion in why imul sets OF in the following instructions

mov  al, 48
mov  bl, 4
imul bl      ; AX = 00C0h, OF = 1

but NOT in the below instructions

mov  ax, 48
mov  bx, 4
imul bx      ; DX:AX = 000000C0h, OF = 0

Solution

  • IMUL sets the overflow flag when the low half of the result, interpreted as a signed integer of the appropriate size, does not equal the mathematical result of multiplying the two input numbers.

    The mathematical result of multiplying 48 by 4 is 192. The value left in AL after imul bl is C0h. As a signed 8-bit integer, that represents the number -64. Mathematically, 192 and -64 are not the same number, so overflow must be set.

    After imul bx, the value left in AX is 00C0h. As a signed 16-bit integer, that represents the number 192. So the overflow flag is not set.

    Equivalently, the overflow flag is set if sign-extending the low half would yield a different value from the full product. When you sign-extend the 8-bit value C0h to 16 bits, you get FFC0h, which does not equal 00C0h, so overflow is set. When you sign-extend the 16-bit value 00C0h to 32 bits, you get 000000C0h, which does equal the actual 32-bit result, so overflow is not set.

    Equivalently, the overflow flag is cleared only if every bit of the high half of the result is equal to the sign bit of the low half. The sign bit of the 8-bit value C0h is 1, but the high half is not FFh, it is 00h, so overflow is set. The sign bit of the 16-bit value 00C0h is 0, and the high half is 0000h, so overflow is cleared.