We're looking for your comments on how to best organize the wiki's content.
Sign
Numbers may be treated either as signed or unsigned numbers. A signed number may be negative, zero or positive, while an unsigned number may only take values equal to, or greater than zero.
Thus, a 16-bit unsigned number may range from 0 to 216-1 (0 to 65535). A 16-bit signed number may range from -215 to 215-1 (-32768 to 32767). Note that the upper boundary value is less for signed numbers than for unsigned, given the same number of bits.
[edit] Two's complement
On the DCPU-16, signed numbers are encoded using two's complement. To convert a negative number to two's complement:
- Take the absolute value of the number N, and subtract one.
- Take the resulting non-negative number and convert it to binary (for conversion instructions, see Decimal, Binary, and Hex).
- Invert all the bits; a 0 becomes 1, and a 1 becomes 0.
A non-negative signed number is represented in binary exactly the same way as any unsigned number. That conversion is described in Decimal, Binary, and Hex.
To convert from two's complement to decimal where the number is negative:
- Invert all the bits.
- Add one.
- Convert this positive number to decimal, and negate it.
For example:
| Binary | Hex | Signed
Decimal Interpretation |
Unsigned
Decimal Interpretation |
|---|---|---|---|
| 0000 0000 0000 00102 | 0x0002 | 2 | 2 |
| 0000 0000 0000 00012 | 0x0001 | 1 | 1 |
| 0000 0000 0000 00002 | 0x0000 | 0 | 0 |
| 1111 1111 1111 11112 | 0xffff | -1 | 65535 |
| 1111 1111 1111 11102 | 0xfffe | -2 | 65534 |
In signed representation, all negative numbers have a 1 as the most significant bit, while zero and positive numbers are indistinguishable from their unsigned representation. Note that negative signed numbers may also be interpreted as rather large positive numbers in unsigned representation.
[edit] Signing dependence of operations
Because negative numbers can also be understood as large positive numbers, a programmer must be careful to use commands that interpret the numbers correctly. Using a command that interprets the number incorrectly may compromise data integrity and cause a program to fail. Take, for example, the following programs. The first program will divide -2 by 2 correctly, while the second will fail:
SET A, -2 ; 0xfffe DVI A, 2 ; signed division (same as ASR A, 1) ; A is now 0xffff, or -1 |
SET A, -2 ; 0xfffe DIV A, 2 ; unsigned division (same as SHR A, 1) ; A is now 0x7fff, or 16,383 ; -- Probably incorrect! |
However, some operations like ADD and SUB behave correctly with both signed and unsigned numbers:
SET A, -9 ; 0xfff7
ADD A, -2 ; 0xfffe
; A is now 0xfff5, or -11
; (Note for the expert: As a side effect, EX has
; registered an overflow and is now 0x0001)
|
SET A, 2 ; 0x0002
SUB A, 9 ; 0x0009
; A is now 0xfff9, or -7
; (Note for the expert: EX has registered
; an underflow and is now 0xffff)
|
To summarize, a good programmer must match signed and unsigned numbers with a compatible operation:
| Operation | Unsigned opcode | Signed opcode | Signing-dependent? |
|---|---|---|---|
| + (Addition) | ADD | No | |
| - (Subtraction) | SUB | No | |
| * (Multiplication) | MUL | MLI | Yes |
| / (Division) | DIV | DVI | Yes |
| % (Modulus) | MOD | MDI | Yes |
| << (Left-shift) | SHL | No | |
| >> (Binary right-shift)
>>> (Arithmetic right-shift) |
SHR | ASR | Yes |
| & (Binary AND) | AND | No | |
| | (Binary OR) | BOR | No | |
| ^| (Binary XOR) | XOR | No | |
| if == (If equal) | IFE | No | |
| if != (If not equal) | IFN | No | |
| if > (If greater than) | IFG | IFA | Yes |
| if < (If less than) | IFL | IFU | Yes |
| if & (If bits) | IFB | No | |
| if !& (if clear) | IFC | No | |
| +_+EX (Add with EX) | ADX | No | |
| -_+EX (Subtract with EX) | SBX | No | |
| =,++ (Set and increment) | STI | No | |
| =,-- (Set and decrement) | STD | No | |
| ||||||||

