Would an arithmetic operation on a pair of signed and unsigned numbers be legal?

I'm more than halfway through the training assembly, and I am familiar with the concept of how signed and unsigned integers are represented in bits, I know this may seem like a strange question, regarding which the answer will be pretty obvious, but I wonder if using an arithmetic operation such as addition makes sense for a pair of numbers, one of which is considered signed and the other unsigned, I thought of several examples, as shown below, which will give the correct result:

10000001 (a 1-byte integer and is considered unsigned, equivalent to 129)
+
11111111 (1-byte integer and considered signed (two-component system), equivalent to -1)


10,000,000 (1-byte integer and in unsigned logic equivalent to 128)

Now, if the upper value was in the AL register, and we had the following command code (in GAS format):

addb -1, %al 

then the carry flag (CF) of the EFLAGS register will be set after the operation is completed and will report an overflow that did not actually occur, and possibly because there is one unsigned number in terms of the overflow of the overflow flag (OF) from the EFLAGS register. Therefore, I am embarrassed if doing such a thing is always reasonable.

+4
source share
5 answers

I found this very enjoyable article on the issue, which was my main concern, and the answer is clear after reading the article.

+1
source

Mathematically, you are not adding a signed or unsigned number. There are only modulo 2 32 values ​​(assuming you have 32-bit registers). These values ​​cover a range of 2,332 consecutive integers, but you can interpret this range as a start almost anywhere. “Signed” and “unsigned” are just two such interpretations.

In other words, with 4-bit registers, the unsigned interpretation of “1011” is eleven, and the signed interpretation is minus five. But there is only one meaning (which mathematicians usually call "eleven modulo 2 4 " because mathematicians traditionally love an unsigned interpretation). For example, if you add “0110” to this value (which is “six” in both signed and unsigned interpretations), then you get “0001”, which is the correct value: minus five plus six lessons one, and eleven plus six - seventeen, which is also equal to one when decreasing modulo 2 4 (seventeen is one plus sixteen, "decreasing modulo 2 4 " means dividing by sixteen (2 4 ] and keeping only the remainder).

Another way of saying this is as follows: the number of (binary) digits for a numerical value is conceptually infinite to the left. The CPU register stores only 32 of the rightmost bits. An unsigned interpretation assumes that conditionally all left bits are equal to zero. The signed interpretation is the assumption that it is conditional that all left bits have the same meaning as bit 31 (i.e., all are equal to zero or they are all equal to one). In any case, when you perform addition (or subtraction or multiplication), the transfer propagates from right to left, and not vice versa, so the values ​​of those ignored bits have nothing to do with the 32-bit result. Thus, there is only one “add” operation code, which does not bother at all about whether its operands are in the programmer’s brain, “signed” or “unsigned”.

When performing an operation that is incompatible with modular arithmetic, the signature must be taken into account. Converting to a sequence of decimal digits for display is such an operation. However, a more frequent case is comparison. Modulo 2 32 values ​​are not ordered; they are in the form of a cyclic loop (when you add 1 to 2 32 -1 and decrease modulo 2 32 you return to 0). Comparison makes sense only when you consider integers in the entire range of integers. At this point, you must decide whether you are using a signed or unsigned interpretation. That is why x86 processors offer both jg (leap, if greater, signed interpretation), and ja (leap, if higher, unsigned interpretation).

+6
source

Regardless of whether a number or operation is signed or not, it is simply a matter of interpretation. What happens when you make the addition is that the two numbers combine to make 10000000 with 1 in the carry flag (because it "came out of the front"). Then, so that your subsequent operations interpret what it means (if you use the bit elsewhere, it looks like you are considering the operation as an unsigned add without wrapping, if you drop the bit, it is as if you were doing a signed add) .

+3
source

At the binary level, there is only one add operation:

  0101 + (5) 1010 = (unsigned 10 or signed -6) -------- 1111 (unsigned 15 or signed -1) 

As for the carry and overflow flags, they are both set according to simple rules. CF can be used to detect oveflow iff , we believe that the operands were unsigned, and OF to detect oveflow iff we consider both signed. Both of these flags are set according to the result, and you decide which of them to use.

The valid formula for the OF flag is

 OF = CF xor MSB_of_result. 

This means that if we add two positive numbers (which we consider to be signed), then if the result is negative, then it will go down.

+3
source

“Signed” and “unsigned” are interpretations. As a rule, assembly instructions have a documented interpretation. I do not know of any architecture where there is an ADD-SIGNED-UNSIGNED that interprets one of its arguments as a signed value, and one as unsigned. This also makes little sense. With 2s complement by integer arithmetic, in any case there will only be a difference in some flag registers.

+1
source

Source: https://habr.com/ru/post/1334900/


All Articles