Home > front end >  Problem in understanding the overflow flag (OF) as defined by the IMUL instruction
Problem in understanding the overflow flag (OF) as defined by the IMUL instruction

Time:08-28

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

CodePudding user response:

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.

CodePudding user response:

OF tells you whether you can truncate the double-width full result back to the input width without changing its value. (When interpreted as a 2's complement integer for imul1, unsigned binary integer for mul.)
0xC0 is the bit-pattern for a negative 8-bit number, but 0x00C0 is a positive 16-bit number.

That's what you want to know if you're using imul or mul as part of a sequence of other 8-bit or 16-bit operations like add, without planning to use the high half of the result.
(Or could be useful to fall back to an extended-precision version that does handle the wider size, if the narrow version is fast enough to be worth branching for.)

If you were already going to use the full width of the output, don't check OF/CF; widening multiply can't overflow in the sense of losing any output bits. The product of two N-bit numbers can always be represented in 2N bits.


Footnote 1: Including the 2 and 3 operand forms like imul cx, dx, 123 that don't write the high half anywhere. Normally you'd use that form for non-widening signed or unsigned math, but if you want to detect when an unsigned multiply wrapped, your best bet is to just use mul even though that forces you to use EAX and have the output in EDX:EAX. See imulq and unsigned long long overflow detection in C and asm

  • Related