I have a few questions about overflow overflow errors in x86 or x86_64 architecture. Recently, I read about integer overflow. Typically, when an arithmetic operation results in an integer overflow, the carry bit or overflow bit is set in the FLAGS register. But apparently, according to this article , overflow resulting from division operations does not set the overflow bit, but rather causes a hardware exception, similar to when you divide by zero.
Now whole overflows resulting from division are much less common than they say multiplication. There are only a few ways to even cause unit overflows. One way is to do something like:
int16_t a = -32768; int16_t b = -1; int16_t c = a / b;
In this case, due to two additional representations of signed integers, you cannot represent a positive 32768 in a 16-bit integer value, therefore, the division operation is overflowed, which leads to an incorrect value of -32768.
A few questions:
1) Contrary to what is said in this article, the foregoing did not cause a hardware exception. I use an x86_64 machine running Linux, and when I divide by zero, the program ends with a Floating point exception . But when I cause the unit to overflow, the program continues, as usual, silently ignoring the erroneous attitude. So why does this not cause a hardware exception?
2) Why are separation errors heavily handled by hardware, unlike other arithmetic overflows? Why should overflow overflow (which is much more likely to happen by accident) be ignored by the hardware, but should a unit overflow trigger a fatal interrupt?
============ EDIT ===============
Ok, thanks everyone for the answers. I got answers saying basically that the above 16-bit integer division should not cause a hardware error, since the factor is still smaller than the register size. I do not understand this. In this case, the register that stores the factor is 16-bit, which is too small to hold a positive positive 32768. So why is there no hardware exception?
Ok, do it right in the GCC inline assembly and see what happens:
int16_t a = -32768; int16_t b = -1; __asm__ ( "xorw %%dx, %%dx;" // Clear the DX register (upper-bits of dividend) "movw %1, %%ax;" // Load lower bits of dividend into AX "movw %2, %%bx;" // Load the divisor into BX "idivw %%bx;" // Divide a / b (quotient is stored in AX) "movw %%ax, %0;" // Copy the quotient into 'b' : "=rm"(b) // Output list :"ir"(a), "rm"(b) // Input list :"%ax", "%dx", "%bx" // Clobbered registers ); printf("%d\n", b);
This simply outputs the erroneous value: -32768 . There is still no hardware exception, even if the register holding factor (AX) is too small to fit the quotient. Therefore, I do not understand why no hardware error occurs here.