Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

would doing arithmetic operation on a pair of signed and unsigned numbers be legal?

I'm more than half way through learning assembly and I'm familiar with the concept of how signed and unsigned integers are presented in bits, I know that it might seem a weird question of which the answer would be pretty obvious, but I'm wondering if using an arithmetic operation like addition makes sense for a pair of numbers that one of them is considered signed and the other one unsigned, I've thought of multiple examples like below that will yield a correct result:

10000001 (1-byte integer and considered unsigned, equivalent to 129)
+
11111111 (1-byte integer and considered signed(two's complement system), equivalent to -1)


10000000 (1-byte integer and in unsigned logic equivalent to 128)

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

addb -1, %al

then the carry flag(CF) of EFLAGS register will be set after the operation's been done and would inform of an overflow that actually has not happened and maybe because there's one unsigned number in terms of an overflow the overflow flag(OF) of EFLAGS register should be referenced. So I'm confused if doing such thing is ever sensible.

like image 717
Pooria Avatar asked Jan 10 '11 09:01

Pooria


People also ask

Can signed and unsigned integers store the same number of values?

Both can store 256 different values, but signed integers use half of their range for negative numbers, whereas unsigned integers can store positive numbers that are twice as large.

Why do we need signed and unsigned integer?

Unsigned can hold a larger positive value and no negative value. Unsigned uses the leading bit as a part of the value, while the signed version uses the left-most-bit to identify if the number is positive or negative. Signed integers can hold both positive and negative numbers.

What are signed and unsigned numbers?

A signed integer is a 32-bit datum that encodes an integer in the range [-2147483648 to 2147483647]. An unsigned integer is a 32-bit datum that encodes a nonnegative integer in the range [0 to 4294967295]. The signed integer is represented in twos complement notation.

What is signed integer arithmetic?

Signed integers are implemented at the processor level in a manner similar to unsigned integers, using something called Two's complement. We can think about Two's complement as a way of mapping signed values to unsigned (binary) values.

Are Immediates signed or unsigned?

Note: ALL arithmetic immediate values are sign-extended. After that, they are handled as signed or unsigned 32 bit numbers, depending upon the instruction. The only difference between signed and unsigned instructions is that signed instructions can generate an overflow exception and unsigned instructions can not.


1 Answers

Mathematically, you do not add signed or unsigned number. There are only values modulo 232 (assuming that you have 32-bit registers). Such values cover a range of 232 consecutive integers, but you are free to interpret that range as beginning just about anywhere. "Signed" and "unsigned" are just two such interpretations.

In other words, with 4-bit registers, the unsigned interpretation of "1011" is eleven, while the signed interpretation is minus-five. But there is only one value (which mathematicians usually call "eleven modulo 24" because mathematicians are traditionally fond of unsigned interpretation). For instance, if you add "0110" to that value (which is "six" in both signed and unsigned interpretations), then you get "0001", which is the proper value: minus-five plus six yield one, and eleven plus six is seventeen which is also equal to one when reduced modulo 24 (seventeen is one plus sixteen; "reducing modulo 24" is about dividing by sixteen [that's 24] and keeping the remainder only).

Another way to say that is the following: the number of (binary) digits for a numerical value is conceptually infinite to the left. The CPU register only keeps the 32 rightmost bits. The unsigned interpretation is about assuming, conventionally, that all the leftmost bits are zero. The signed interpretation is about assuming, conventionally, that all the leftmost bits have the same value than the bit 31 (i.e. all are zero, or all are one). Either way, when you perform an addition (or a subtraction or a multiplication), carries propagate from right to left, not the other way round, so the values of those ignored bits have no bearing whatsoever on the 32-bit result. So there is only one "add" opcode, which does not care the slightest bit about whether its operands are, in the brain of the programmer, "signed" or "unsigned".

Signedness must be taken into account when performing an operation which is not compatible with modulo arithmetics. Conversion into a sequence of decimal digits for display is such an operation. A more frequent case, however, is comparisons. Values modulo 232 are not ordered; they are in a kind of cyclic loop (when you add 1 to 232-1, and reduce modulo 232, you get back to 0). Comparisons make sense only when you consider integers in the whole range of integers. At that point, you must decide whether you use the signed or unsigned interpretation. Which is why x86 processors offer both jg (jump if greater, signed interpretation) and ja (jump if above, unsigned interpretation).

like image 144
Thomas Pornin Avatar answered Nov 15 '22 12:11

Thomas Pornin