-2147483648 bytes .-.
-2147483648 bytes .-. is an esolang by User:TheBigH, inspired by -25 bytes (O_o) which is inspired by -5 bytes ;) which is inspired by 0 bytes XD which is inspired by 9 bytes :I which is inspired by 13 bytes :D which is inspired by 16 bytes :P which is inspired by 25 bytes o:.
Machine Language
The machine language is somewhat similar to that of other early processors, except that the address space is very small.
The computer has a main memory consisting of 256 individually addressable nybbles (a nybble means 4 bits), used for both data and code. There is also a one byte long accumulator register, a one byte long program counter, two status flags (carry and zero). There's also a so-called data flag that reads user input from a microswitch if I understand correctly.
Instructions are read from the main memory, normally sequentially, but altered by jumps. Each instruction is either one nybble long or three nybble long: the first nybble gives the opcode, the next two are interpreted in various ways depending on the opcode. The instructions that access data in the memory always access two adjacent nybbles together, interpreted as a byte stored as two nybbles in big-endian. Addresses are measured in nybbles, so data need not be aligned. The instructions are the following (opcode in parenthesis).
Opcode | Mnemonic | Size | Description |
---|---|---|---|
0 | HLT | 1 | Halts the processor. |
1 | LDA nn | 3 | Load 8-bit value from address nn into accumulator. |
2 | STA nn | 3 | Store accumulator into 8-bit address nn. |
3 | JMP nn | 3 | Jump to (set program counter to) nn. |
4 | SPC nn | 3 | Store value of program counter to address nn. |
5 | AND nn | 3 | Bitwise AND the value of the accumulator with nn. Update Z (zero) flag. |
6 | OR nn | 3 | Bitwise OR the value of the accumulator with nn. Update Z (zero) flag. |
7 | ADD nn | 3 | Add nn to the accumulator. Update C (carry) and Z (zero) flags. |
8 | SUB nn | 3 | Subtract nn from the accumulator. Update C (carry) and Z (zero) flags. |
9 | JNZ nn | 3 | Jump to nn, but only if the Z (zero) flag is not set. |
A | CMP nn | 3 | Subtract nn from the accumulator, but instead of storing the result in the accumulator, discard the result. Update C (carry) and Z (zero) flags. (C will be set if nn is greater, Z will be set if they're the same, no flags if accumulator is greater) |
B | JND nn | 3 | Jump to nn, but only if the D (data) flag is not set. (D flag is controlled by user) |
C | JNC nn | 3 | Jump to nn, but only if the C (carry) flag is not set. |
D | ROL | 1 | Rotate the accumulator left. Move C to the least significant bit, move the most significant bit to C. |
E | ROR | 1 | Rotate the accumulator right. Move C to the most significant bit, move the least significant bit to C. |
F | CLF | 1 | Clear the flags. |
The machine language is completely specified without space for extension, since all opcodes have a defined meaning, and all addresses correspond to memory that exists. This should not be surprising, given that the goal was a single hardware implementation.
The arithmetic operations take an immediate operand, so you have to use self-modifying code with the STA instruction to use other operands. Similarly, you would have to use self-modifying code to load or store from an indexed (non-constant) address, or to jump indirectly. Thus, the machine language favors self-modifying code even more than the 6502 processor does.
The machine language itself is described on the (original) creator's webpage.
Examples
The main page that gives a summary of the Processor also gives two example programs.
Implementation
Take a normal interpreter for Viktor's amazing 4-bit processor and add bytes until you reach 2147483648, at which point it will overflow and become -2147483648 bytes.