In ASM it is very simple:
Code: Select all
test eax, eax
.IF SIGN?
; do operations here
.ELSE
; other operations here
.ENDIF
or
Code: Select all
cmp eax, 5
js @@is_signed ; test SIGN flag
CPU has a lot of flags for such things. the most important are: Carry Flag, Zero Flag, Sign Flag, Overflow Flag.
And yes in reality there are only numbers, mostly unsigned ones for ALU without multiply/div. FPU does have a convention for negative zero and bit paterns that are "not a number".
Signed is a convention, a way to bias the number range in two partitions.
The most used or common convention is that the most significant bit represents the SIGNED / UNSIGNED status of the data and for the actual value it is a Two's complement.
The problem is in High Level Languages like C / C++ etc. They do not expose or have access to the Carry Flag. However they do have access to the signed flag hence the signed / unsigned casting and multiple problems with unsigned overflows that would have been detected by Carry flag.
Probably at the time high level languages have been designed most CPU's only had a Signed flag and no Carry or Overflow flag.
And probably by the time other much higher level languages have been designed their creators did not even know what a "flag" or a CPU is anymore ...