Program Code
Write your assembly code below.
Controls
CPU State
Status
Idle
Program Counter
0
Compare Flag
0
Dedicated Counter 1
0
Dedicated Counter 2
0
Error
-
A simple Turing Machine simulated on the CPU, increments a binary number on the tape (RAM).
Write your assembly code below.
Idle
0
0
0
0
-
A **Turing-complete** system is one that can simulate any Turing machine. A Turing machine is a theoretical model of computation that consists of a tape (infinite memory), a head that can read and write symbols on the tape, and a set of rules (program) that dictate its behavior. If a system can simulate a Turing machine, it means it can perform any computation that any other computer can perform, given enough time and memory.
However, real-world computers (like this simulation) have **finite memory**. This fundamental limitation means they are technically not truly Turing-complete. But, for practical purposes, if their instruction set and control flow capabilities are rich enough, they are considered "mostly" Turing-complete because they can simulate the *computational aspects* of a Turing machine, assuming the problem fits within their memory constraints.
This CPU simulation, despite its finite RAM, possesses the necessary instructions (arithmetic, data movement, conditional jumps) to simulate other computational models like a Register Machine, which in turn are known to be Turing-equivalent. Therefore, in theory (ignoring memory limits), it can perform universal computation.
This interactive application simulates a very basic Central Processing Unit (CPU) with a small set of assembly-like instructions:
Key Instructions:
Arithmetic expressions can now be used as arguments for `MOV`, `ADD`, `SUB`, `LOAD`, `STOR`, `OUT`, and `CMP` instructions. Supported operators are `+`, `-`, `*`, `/`. Expressions must be in the format `Operand Operator Operand` (e.g., `A + 1`, `B * C`). Division performs integer division (result is floored). Additionally, using `$` as an operand in an expression will reference the current value of Dedicated Counter 1, and `$2` will reference Dedicated Counter 2 (e.g., `STOR A, $`, `ADD B, $2 + 5`).
This section provides a detailed guide on each instruction available in this CPU's assembly language, including their purpose, syntax, arguments, and practical examples.
Purpose: Copies a value, the content of one register, or the result of an arithmetic expression into another register.
Syntax: `MOV DEST_REG, SOURCE`
Behavior: The value of `SOURCE` is copied into `DEST_REG`. The `SOURCE` itself is unchanged.
Example:
MOV A, 10 ; Register A becomes 10 MOV B, A ; Register B becomes 10 (value from A) MOV C, -5 ; Register C becomes -5 MOV D, A + 5 ; Register D becomes 15 (if A was 10) MOV A, B * C ; Register A becomes -50 (if B was 10, C was -5) MOV B, $ + 1 ; Register B becomes (dedicatedCounter + 1) MOV D, $2 - 3 ; Register D becomes (dedicatedCounter2 - 3)
Purpose: Adds a value, the content of one register, or the result of an arithmetic expression to another register.
Syntax: `ADD DEST_REG, SOURCE`
Behavior: `DEST_REG = DEST_REG + SOURCE`. `SOURCE` is unchanged.
Example:
MOV A, 5 ; A = 5 MOV B, 3 ; B = 3 ADD A, B ; A = A + B (A becomes 8) ADD C, 10 ; C = C + 10 (assuming C was 0, C becomes 10) ADD D, A / 2 ; D = D + (A / 2) (integer division) ADD A, $ ; A = A + dedicatedCounter ADD B, $2 ; B = B + dedicatedCounter2
Purpose: Subtracts a value, the content of one register, or the result of an arithmetic expression from another register.
Syntax: `SUB DEST_REG, SOURCE`
Behavior: `DEST_REG = DEST_REG - SOURCE`. `SOURCE` is unchanged.
Example:
MOV A, 10 ; A = 10 MOV B, 3 ; B = 3 SUB A, B ; A = A - B (A becomes 7) SUB D, 1 ; D = D - 1 (decrement D) SUB B, A - C ; B = B - (A - C) SUB C, $ ; C = C - dedicatedCounter SUB D, $2 ; D = D - dedicatedCounter2
Purpose: Copies a value from a specified RAM address (which can be an expression) into a register.
Syntax: `LOAD DEST_REG, ADDRESS`
Behavior: `DEST_REG = RAM[ADDRESS]`. The content of RAM at `ADDRESS` remains unchanged.
Example:
MOV A, 5 ; Register A becomes 100 MOV B, 2 LOAD C, 3 + B ; Register C becomes RAM[5] (if B was 2) LOAD D, 10 + $ ; Register D becomes RAM[10 + dedicatedCounter] LOAD A, 30 + $2 ; Register A becomes RAM[30 + dedicatedCounter2]
Purpose: Copies a value from a register into a specified RAM address (which can be an expression).
Syntax: `STOR SOURCE_REG, ADDRESS`
Behavior: `RAM[ADDRESS] = SOURCE_REG`. The content of `SOURCE_REG` is then cleared to 0. Other registers (not `SOURCE_REG`) will retain their values.
Example:
MOV A, 25 ; A = 25 MOV B, 10 ; B = 10 STOR A, 10 ; RAM[10] becomes 25. A becomes 0. B, C, D remain unchanged. MOV C, 1 STOR B, B + C ; RAM[11] becomes B's value (10). B becomes 0. STOR D, $ ; RAM[dedicatedCounter] becomes D's value. D becomes 0. STOR A, $2 ; RAM[dedicatedCounter2] becomes A's value. A becomes 0.
Purpose: Reads the next number from the Input area into a specified register.
Syntax: `INP DEST_REG`
Behavior: The first available number from the Input area is consumed and placed into `DEST_REG`. If no input is available, the CPU will pause execution until input is provided.
Example:
; Input area has: ; 42 ; 100 INP A ; A becomes 42. Input area now has: 100 INP B ; B becomes 100. Input area is now empty.
Purpose: Displays a value, the content of a register, or the result of an arithmetic expression in the Output area.
Syntax: `OUT SOURCE`
Behavior: The value of `SOURCE` is appended as a new line to the Output area.
Example:
MOV A, 7 OUT A ; Output: 7 OUT 99 ; Output: 99 (on a new line) OUT A * 2 ; Output: 14 (if A was 7) OUT $ ; Output: current value of Dedicated Counter 1 OUT $2 ; Output: current value of Dedicated Counter 2
Purpose: Compares two values (which can be expressions) and sets the `Compare Flag` based on their relationship.
Syntax: `CMP VALUE1, VALUE2`
Behavior: Sets the `Compare Flag` register:
This flag is then used by conditional jump instructions (`JEZ`, `JNE`, `JGT`, `JLT`).
Example:
MOV A, 5 MOV B, 10 CMP A, B ; Compare Flag = -1 (5 < 10) CMP B, 5 ; Compare Flag = 1 (10 > 5) CMP A, 5 ; Compare Flag = 0 (5 == 5) CMP A + 1, B ; Compare Flag = -1 (6 < 10) CMP $, 10 ; Compare Flag based on Dedicated Counter 1 vs 10 CMP $2, B ; Compare Flag based on Dedicated Counter 2 vs B
Purpose: Increments Dedicated Counter 1 ($) by 1.
Syntax: `INC` (takes no arguments)
Behavior: The `Dedicated Counter 1` variable is incremented by 1. This instruction is useful for tracking loop iterations or other custom counts.
Example:
MOV A, 3 LOOP_COUNT: INC ; Dedicated Counter 1 increments SUB A, 1 CMP A, 0 JNE LOOP_COUNT OUT $ ; Output: final value of Dedicated Counter 1
Purpose: Increments Dedicated Counter 2 ($2) by 1.
Syntax: `INC2` (takes no arguments)
Behavior: The `Dedicated Counter 2` variable is incremented by 1.
Example:
MOV A, 5 LOOP_INNER: INC2 ; Dedicated Counter 2 increments SUB A, 1 CMP A, 0 JNE LOOP_INNER OUT $2 ; Output: final value of Dedicated Counter 2
Purpose: Unconditionally changes the `Program Counter` (PC) to the address of a specified label, causing execution to continue from that point.
Syntax: `JMP LABEL_NAME`
Behavior: The PC is set to the line number associated with `LABEL_NAME`. This creates loops or jumps to subroutines.
Example:
MOV A, 1 OUT A HLT ; Program stops here MOV B, 2 ; This line will never be reached
Purpose: Jumps to a label if the `Compare Flag` is 0 (meaning the last `CMP` operation resulted in equality).
Syntax: `JEZ LABEL_NAME`
Behavior: If `Compare Flag == 0`, PC is set to `LABEL_NAME`. Otherwise, execution continues to the next instruction.
Example:
MOV A, 5 CMP A, 5 ; Compare Flag = 0 JEZ IS_FIVE ; Jumps to IS_FIVE OUT 0 ; This line is skipped IS_FIVE: OUT 1 ; Output: 1 HLT
Purpose: Jumps to a label if the `Compare Flag` is not 0 (meaning the last `CMP` operation resulted in inequality).
Syntax: `JNE LABEL_NAME`
Behavior: If `Compare Flag != 0`, PC is set to `LABEL_NAME`. Otherwise, execution continues to the next instruction.
Example:
MOV A, 5 CMP A, 6 ; Compare Flag = -1 JNE NOT_SIX ; Jumps to NOT_SIX OUT 0 NOT_SIX: OUT 1 ; Output: 1 HLT
Purpose: Jumps to a label if the `Compare Flag` is 1 (meaning the first value in `CMP` was greater than the second).
Syntax: `JGT LABEL_NAME`
Behavior: If `Compare Flag == 1`, PC is set to `LABEL_NAME`. Otherwise, execution continues to the next instruction.
Example:
MOV A, 10 MOV B, 5 CMP A, B ; Compare Flag = 1 JGT A_IS_GREATER ; Jumps to A_IS_GREATER OUT 0 A_IS_GREATER: OUT 1 ; Output: 1 HLT
Purpose: Jumps to a label if the `Compare Flag` is -1 (meaning the first value in `CMP` was less than the second).
Syntax: `JLT LABEL_NAME`
Behavior: If `Compare Flag == -1`, PC is set to `LABEL_NAME`. Otherwise, execution continues to the next instruction.
Example:
MOV A, 5 MOV B, 10 CMP A, B ; Compare Flag = -1 JLT A_IS_LESS ; Jumps to A_IS_LESS OUT 0 A_IS_LESS: OUT 1 ; Output: 1 HLT
Purpose: Stops the CPU execution.
Syntax: `HLT` (takes no arguments)
Behavior: The program halts, and the CPU status changes to "Halted".
Example:
MOV A, 1 OUT A HLT ; Program stops here MOV B, 2 ; This line will never be reached
The example program loaded by default demonstrates how to simulate a simple Turing Machine. This TM's purpose is to **increment a binary number** stored on a "tape" within the CPU's RAM.
The "tape" is a segment of RAM starting at address `RAM[10]`. Each cell contains a `0` or `1` for binary digits, and `2` represents a blank symbol. For example, the initial tape `0, 1, 1, 2, 2` represents the binary number "011".
The TM works by starting its "tape head" (Register A) at the rightmost digit of the binary number. It then processes the digits from right to left, performing additions with carry, similar to how you would manually increment a binary number:
Given the updated `STOR` instruction (which only clears the source register), the Turing machine program will still function correctly as it explicitly manages the tape head position by saving it to and loading it from `RAM[0]`. While the original program had to account for *all* registers being cleared, this updated behavior of `STOR` simplifies register management for other variables, as they will now persist across `STOR` operations unless they are the source register.
After the increment operation completes, the program iterates through the modified tape (RAM[10] to RAM[14]) and outputs each symbol to the I/O output area, showing the result of the Turing machine's work.