24

-1 can be represented in 4 bit binary as (2's complement) 1111

15 is also represented as 1111.

So, how does CPU differentiate between 15 and -1 when it gets values from memory?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
MCG
  • 1,011
  • 1
  • 10
  • 21

5 Answers5

20

The CPU doesn't care whether a byte holds -1 or 15 when it moves it from one place to another. There's no such thing as a "signed move" (to a location of the same size - there is a signed move for larger or smaller destinations).

The CPU only cares about the representation when it does arithmetic on the byte. The CPU knows whether to do signed or unsigned arithmetic according to the op-code that you (or the compiler on your behalf) chose.

Peter vdL
  • 4,953
  • 10
  • 40
  • 60
  • Signed and unsigned arithmetic matters only in case of 1s complement. In 2's complement the sign is self evident. – Amal Antony Oct 06 '11 at 22:17
  • `11111111b + 00000001b`, @amalantony: this overflows if both quantities are unsigned (assuming 8bit regs). It does not overflow if they are signed. The compiler can't tell the difference if it doesn't have information about the type _somewhere_ (in the opcode or some flags for instance) – Mat Oct 06 '11 at 22:21
  • @Peter how does the system decide whether 15(1111b)-1 =14 and -1(1111b)-1(0001b)=-2 – MCG Oct 06 '11 at 22:22
  • @amal: Signed vs. unsigned does make a difference in twos-complement representation. The instruction set would probably provide separate opcodes for signed and unsigned comparison, for example. And a C compiler would emit the appropriate compare instruction depending on the C types (signed vs. unsigned) of the operands. – Jim Lewis Oct 06 '11 at 22:24
  • @MCG: That would be a bad example, because 1111b - 0001b = 1110b, which can interpreted as unsigned (15 - 1 = 14) or signed (-1 - 1 = -2) correctly. Multiply and divide, though, require different instructions for signed vs unsigned. – Elliot Nelson Oct 06 '11 at 22:34
  • @JimLewis: I answered the original question from the perspective of the compiler. I think MCG wants to know how the representation of 15 and -1 is different from each other in the 2s complement form. When it comes to the CPU it all boils down to the type of opcode generated, like what Peter and you mentioned. – Amal Antony Oct 06 '11 at 22:48
10

Most of the previous answers mentioned separate opcodes. That might be true for more complicated operations like multiplication and division, but for simple addition and subtraction that is not how the CPU works.

The CPU keeps data about the result of an instruction in its flags register. On x86 (where I am most familiar) the two most important flags here are the "overflow" and "carry" flags.

Basically the CPU doesn't care if the number is signed or unsigned it treats them both the same. The carry flag is set when the number goes over the highest unsigned value it can contain. The overflow flag is set when it goes over or under the range of an unsigned number. If you are working with unsigned numbers you check the carry flag and ignore the overflow flag. If you are working with signed numbers you check the overflow flag and ignore the carry flag.

Here are some examples:

Unsigned:

1111 (15) + 1111 (15) = 1110 (14)

What you do now is check the carry flag, which in this case contains one giving the final result

1 1110 (30)

Signed:

1111 (-1) + 1111 (-1) = 1110 (-2)

In this case you ignore the carry flag, the overflow flag should be set to zero.

Unsigned:

0111 (7) + 0111 (7) = 1110 (14)

When you check the carry flag it should be zero.

Signed:

0111 (7) + 0111 (7) = 1110 (-2)

In this case the overflow flag would be set meaning that there was an error in the addition.

So in summary the number is only signed or unsigned based on your interpretation of it, the CPU gives you the tools nessecary to distinguish between them, but doesn't distinguish on its own.

john
  • 157
  • 2
  • 6
7

The CPU doesn't know if a number is signed or unsigned. When the compiler creates the machine language file, it chooses the correct operation to be executed to make a math operation with that number. If you declared your variable to be of the signed type, for instance, than the operation to be executed in machine language will be one that treats that memory position as a signed value.

In any software of any kind, it is always when you interpret the data that you give it meaning. A byte in memory can be a signed or unsigned number, or a character, or a part of a music file, or a pixel in a picture, etc. What gives it meaning is how you use that byte.

nobody
  • 19,814
  • 17
  • 56
  • 77
user3765039
  • 81
  • 1
  • 1
2

At the compiler level, the differentiation is based on data type. If the data type is int, then 4 bytes is allocated to that variable (in C). So 15 in 2's complement is 00000000 00000000 00000000 00000000 00001111 while -1 is 11111111 11111111 11111111 11111111 . The compiler then converts this to the corresponding opcode of the CPU. The CPU executes this opcode and at this level everything is in the form of 1s and 0s.

Amal Antony
  • 6,477
  • 14
  • 53
  • 76
  • 6
    That doesn't answer the question, which how the CPU makes a difference. The CPU doesn't know C. – Mat Oct 06 '11 at 22:11
  • The compiler allocates a predefined number of bytes to each number (irrespective of the language, C was just an example). If the binary version consists of all 1s, then its -1, if there is at least 1 preceding 0 bit, its interpreted as a non 0 integer value. Did u get it? – Amal Antony Oct 06 '11 at 22:14
  • Which raises the question, how would the CPU distinguish between 32-bit values -1 and 2^32 - 1, both of which have the same bit representation in twos-complement? – Jim Lewis Oct 06 '11 at 22:16
  • No. The question is: say I have `unsigned char i=255;` That is `11111111` in binary. `11111111` would be -127 with a signed char. The CPU doesn't have access to type information from the language. How can it tell which is which? (I'm not saying the question is actually answerable since it depends _completely_ on the actual CPU/instruction set, just saying your answer doesn't answer the question.) – Mat Oct 06 '11 at 22:16
  • @amal what happens, when it is a 4 bit machine? – MCG Oct 06 '11 at 22:17
  • MCG: In a 4-bit m/c the highest legal value which can be stored is 0111. If I store a bigger number the datatype overflows and the value becomes -1. @Mat: I think that was the answer MCG was looking for. With regards to your question, the binary values are interpreted according to the data type the programmer specifies (or context in scripting languages). – Amal Antony Oct 06 '11 at 22:22
  • @amalantony: _the CPU doesn't see the types defined in high level language_. The compiler has to emit its code in such a way that the CPU knows what type of values are stored and what type of operations they need (signed or not). That would answer the question. – Mat Oct 06 '11 at 22:28
  • @Mat: Yeah .. i think Peter has a point there. It all boils down to the opcode generated by the compiler. CPU doesn't care. I was showing MCG how the 2s complement representation of -1 and 15 are different :) – Amal Antony Oct 06 '11 at 22:34
0

In 2's complement to represent 15 we require 5 bits the range for 2'complemnt is -16 to 15,so the value become 01111 here the MSB bit is 0 so its positive value for -1 it will become 11111

goodman
  • 424
  • 8
  • 24