0

The following example should set both the carry and overflow flag:

mov eax, -120
add al, 140

add al, 140 will resemble the following operation in bit:

 10001000
+10001100
---------
= 100010100

So the result has 9 bits while the maximum amount of bits that can be put in al is 8. But the way I understand the overflow-flag it's only set when the result of an operation is "wrong". For E.g. when adding a positive number to a positive number but then the sign-flag is set so it yields a negative result.

And regarding the carry flag in the examples I've done so far, I only set it when I subtract a smaller value from a bigger value.

So my question boils down to how the carry and overflow flag behaves when the size of the operation can't be represented in the register.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
stht55
  • 390
  • 1
  • 8
  • Does this answer your question? [about assembly CF(Carry) and OF(Overflow) flag](https://stackoverflow.com/questions/791991/about-assembly-cfcarry-and-ofoverflow-flag) – Erik Eidt Apr 04 '22 at 16:56
  • See also: http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt – Erik Eidt Apr 04 '22 at 16:59
  • Is it correct that in this case the carry (out) flag is set as result > available and the overflow flag bc. `- v1 + (-v2) != + res` So the result should be negative but is positive as the sign bit go pushed out? – stht55 Apr 04 '22 at 17:40

1 Answers1

2

Ok, the problem that you have here is a mismatch with how computer data types work and what you're doing.

In general the computer can work with (i.e. add) signed data types or unsigned data types — but it can be problematic to ask it to add a signed value to an unsigned value.

Here, -120 is negative, so must use a signed representation.

However, 140 itself does not fit in 8-bit signed, so in 8 bits, must use an unsigned representation.

This combination is not supported by the hardware — while the addition will work to give a truncated result, the hardware will not give you meaningful information in the flags if you perform 8-bit addition.

(The flags for an 8-bit addition are meaningful if both operands are 8-bit signed or else if both operands are 8-bit unsigned, but they are not always meaningful when mixing the two data types: in particular when the values involved are sufficiently large such that the upper bits are in use, as is the case with -120signed 8 bit and 140unsigned 8 bit)

The approach to use to get proper results here is to convert both numbers to a larger data size that will accommodate both numbers (it will be a signed data type so it can accommodate -120, and of course, the method of conversion will differ for the two operands as they are different data types).

So, convert -120 from 8 bit to 16 bit (or larger) by sign extension.

And, convert 140 from 8 bit to 16 bit (or larger) by zero extension.

Then you can perform addition and get a signed result, with a meaningful overflow flag.  Of course that particular computation won't overflow in 16 bits — in fact, no addition in 16 bits that started with two 8-bit values can overflow.

However, if you want to take it back to 8 bits, you can check to see if it fits in that size & data type.  For all practical purposes, in this scenario the upper 8 bits of the 16-bit result contains the overflow information of interest regarding the lower 8-bit result, rather than that information being in the flags (overflow/carry).

First, decide which 8-bit data type you want to check: as to signed or unsigned.  There are several approaches that would work, but a simple one is to truncate the 16-bit value to 8 bits, the expand it back from 8 to 16, and see if that newly expanded 16 equals the original 16-bit result.

For signed 8 bit, you would truncate the 16-bit result to 8 bits and then sign extend it back to 16-bits, then to compare with the original 16-bit value.  If it differs the value didn't fit in 8-bits signed.

The same with unsigned 8 bit: truncate the 16-bit result to 8 bits and zero extend it back to 16 bits to compare with the original, if it doesn't compare equal then it doesn't fit in 8-bits unsigned.

Alternately, from the 16-bit original result, you can examine the sign bit of the low 8-bit value and the value of the upper 8 bits.  If all the upper bits are the same bit value as the sign bit of the lower 8 bits then the 16-bit result will fit in 8-bits signed without loss.

For unsigned, if the upper 8 bits are 0 the lower 8 will fit in 8-bit unsigned without loss.

Erik Eidt
  • 23,049
  • 2
  • 29
  • 53
  • Thank you for the elaborate answer makes a lot more sense now. One follow-up question: `move al, -120` and then `add al, -120` would it be correct that here both the `cf` and `of` will be set as the sign bit got pushed out without 16-bit extension? (100010000 <- first bit pushed out) – stht55 Apr 04 '22 at 19:00
  • 2
    The -120 signed, is the same bit pattern as 136 unsigned. The `cf` flag will reflect the carry (unsigned overflow) of 136 + 136 (272 does not fit in 8-bits unsigned), while the `ov` flag will reflect the signed overflow of -120 + -120 (-240 does not fit in 8-bits signed). – Erik Eidt Apr 04 '22 at 19:04