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
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.