0

I was recently studying about two's complement and how we can use the same hardware to do add, subtract and multiply two numbers regardless of whether they are signed or unsigned. Then i remembered that in static compiled languages such as C we need to explicitly tell to the compiler if the number is signed or unsigned.

I Do understand that while the CPU ALU (i think) does not need (or does not want) to know if the number is signed or unsigned, but the compiler needs! so we can do the correct computations, comparisons, and handle input/output better.

My low-level inclined question is:

At the lowest level, does the computer REALLY doesn't need to know if the numbers are signed or not, is it really a COMPILER-ONLY concern ?

I Did some experiments here some of the interesting results:

(C Code) Changing if the b is signed or unsigned in code

Generated Assembly from the C code (comparison parts only)

Not much of a difference in the assembly code, but it does differ, which i found interesting. So it seems that signed or unsigned is just a compiler and programmer concern, so we can generate the correct code, i am missing something ?, some low-level detail ?, does the cpu totally ignores if the number is signed or not ?

The cpu totally ignores if the number is signed or unsigned ?

  • The CPU doesn't always ignore if the number is signed or not. That's why we have `MUL` and `IMUL`, `SAR` and `SHR`. – W. Chang May 09 '21 at 06:50
  • So MOST of the time we can safely ignore if the number is signed, that's the power of two's complement – BottomExplorer May 09 '21 at 06:54
  • 1
    No we can't: which is smaller? `0x0000` or `0xFFFF`? The processor does not have a signed and unsigned version: the programmer must test the appropriate flags. By specifying `signed` or `unsigned` the C compiler does that for you. – Weather Vane May 09 '21 at 07:08
  • ...and used as an array index or pointer arithmetic, it really does matter for the larger index values (more than half the unsigned range). – Weather Vane May 09 '21 at 07:14
  • 2
    @BottomExplorer Basically, we can only ignore that for addition and subtraction. But these are already the two most common operations, so it's quite useful. – fuz May 09 '21 at 09:03
  • 1
    Most of the time? Besides addition and subtraction (`ADD`, `SUB`, `ADC`, `SBB`, `DEC`, `INC`, `CMP`), only left shift (`SHL`/`SAL`) works on both signed and unsigned numbers. Multiply, division, right shift, negation (`NEG`), `CWD/CDQ/CQO`, and `MOVZX/MOVSX` don't. And if you consider SIMD instructions, many addition and subtraction instructions are signedness-aware. – W. Chang May 09 '21 at 09:25
  • 1
    Even though ADD & SUB work on both signed and unsigned numbers, they set the flags so that we can tell overflow: overflow is different depending on whether the addition was intended as signed or unsigned -- we would test different flags. – Erik Eidt May 09 '21 at 10:17
  • 1
    @W.Chang Multiplication works, too, if you do not need the high word of the result. – fuz May 09 '21 at 10:25
  • @fuz Yes, you're right. That's the case for `IMUL` with two or three operands. For `MUL/IMUL` with 1 operand, `DX/EDX/RDX` is modified and will be different. – W. Chang May 09 '21 at 11:55

0 Answers0