JustPaste
HomeCategoriesAboutDonateContactTerms of UsePrivacy Policy
JustPaste

Free online notepad — write and share instantly

Navigate

  • Home
  • Timeline
  • Categories

Info

  • About
  • Donate
  • Contact

Legal

  • Terms of Use
  • Privacy Policy

© 2026 JustPaste.app. All rights reserved.

Made with ♥ by JustPaste

Untitled Page | JustPaste.app
23 days ago3 views
👨‍💻Programming

Untitled Page

# MINI COMPUTER EMULATOR
# Command-line virtual computer with an interactive assembly editor.

MEMORY_SIZE = 256
REGISTERS = ("A", "B", "C", "D")
MAX_STEPS = 10000

HELP = """
INSTRUCTIONS
  SET A, 10     Set register A to 10
  MOV A, B      Copy register B into A
  ADD A, B      Add B to A
  SUB A, B      Subtract B from A
  INC A         Increment A
  DEC A         Decrement A
  LOAD A, 10    Read memory address 10 into A
  STORE A, 10   Write A into memory address 10
  JMP LOOP      Jump to a label
  JNZ A, LOOP   Jump if A is not zero
  JZ LOOP       Jump if the zero flag is set
  PRINT A       Print register A
  HALT          Stop the program

Use labels like LOOP:
Use ; for comments.
"""


class Assembler:
    ARITY = {
        "SET": 2, "MOV": 2, "ADD": 2, "SUB": 2,
        "INC": 1, "DEC": 1, "LOAD": 2, "STORE": 2,
        "JMP": 1, "JNZ": 2, "JZ": 1, "PRINT": 1,
        "HALT": 0,
    }

    def assemble(self, source):
        lines = []
        labels = {}

        for line_no, raw in enumerate(source.splitlines(), 1):
            line = raw.split(";", 1)[0].strip()
            if not line:
                continue

            if ":" in line:
                label, line = line.split(":", 1)
                label = label.strip().upper()

                if label in labels:
                    raise ValueError(
                        f"Line {line_no}: duplicate label {label}"
                    )

                labels[label] = len(lines)
                line = line.strip()
                if not line:
                    continue

            parts = line.split(None, 1)
            op = parts[0].upper()
            args = (
                [x.strip().upper() for x in parts[1].split(",")]
                if len(parts) > 1 else []
            )
            lines.append((op, args, line_no))

        if len(lines) > MEMORY_SIZE:
            raise ValueError("Maximum program size is 256 instructions.")

        program = []

        for address, (op, args, line_no) in enumerate(lines):
            if op not in self.ARITY:
                raise ValueError(f"Line {line_no}: unknown instruction {op}")

            if len(args) != self.ARITY[op]:
                raise ValueError(f"Line {line_no}: incorrect operand count")

            args = [labels.get(arg, arg) for arg in args]

            reg_positions = {
                "SET": (0,), "MOV": (0, 1), "ADD": (0, 1),
                "SUB": (0, 1), "INC": (0,), "DEC": (0,),
                "LOAD": (0,), "STORE": (0,), "JNZ": (0,),
                "PRINT": (0,),
            }.get(op, ())

            for pos in reg_positions:
                if args[pos] not in REGISTERS:
                    raise ValueError(
                        f"Line {line_no}: invalid register {args[pos]}"
                    )

            numeric_positions = {
                "SET": (1,), "LOAD": (1,), "STORE": (1,),
                "JMP": (0,), "JNZ": (1,), "JZ": (0,),
            }.get(op, ())

            for pos in numeric_positions:
                try:
                    value = int(args[pos], 0)
                except ValueError:
                    raise ValueError(
                        f"Line {line_no}: invalid number or label {args[pos]}"
                    )

                if op == "SET" and not 0 <= value <= 255:
                    raise ValueError("SET values must be 0-255.")

                if op in ("LOAD", "STORE") and not 0 <= value < MEMORY_SIZE:
                    raise ValueError("Memory addresses must be 0-255.")

                if op in ("JMP", "JNZ", "JZ") and not (
                    0 <= value < len(lines)
                ):
                    raise ValueError("Invalid jump destination.")

            program.append((op, args, line_no))

        return program


class Computer:
    def __init__(self):
        self.reset()

    def reset(self):
        self.memory = [0] * MEMORY_SIZE
        self.registers = {r: 0 for r in REGISTERS}
        self.pc = 0
        self.zero = False
        self.halted = False
        self.steps = 0
        self.output = []

    def execute(self, op, args):
        r = self.registers

        def setr(name, value):
            r[name] = value & 255
            self.zero = r[name] == 0

        def address(text):
            value = int(text)
            if not 0 <= value < MEMORY_SIZE:
                raise ValueError("Memory address must be 0-255.")
            return value

        if op == "SET":
            setr(args[0], int(args[1]))
        elif op == "MOV":
            setr(args[0], r[args[1]])
        elif op == "ADD":
            setr(args[0], r[args[0]] + r[args[1]])
        elif op == "SUB":
            setr(args[0], r[args[0]] - r[args[1]])
        elif op == "INC":
            setr(args[0], r[args[0]] + 1)
        elif op == "DEC":
            setr(args[0], r[args[0]] - 1)
        elif op == "LOAD":
            setr(args[0], self.memory[address(args[1])])
        elif op == "STORE":
            self.memory[address(args[1])] = r[args[0]]
        elif op == "JMP":
            self.pc = int(args[0])
        elif op == "JNZ":
            if r[args[0]] != 0:
                self.pc = int(args[1])
        elif op == "JZ":
            if self.zero:
                self.pc = int(args[0])
        elif op == "PRINT":
            message = str(r[args[0]])
            self.output.append(message)
            print("OUTPUT:", message)
        elif op == "HALT":
            self.halted = True

    def run(self, program, step_mode=False):
        self.reset()

        while not self.halted:
            if not 0 <= self.pc < len(program):
                print("Program ended.")
                break

            if self.steps >= MAX_STEPS:
                print("Execution limit reached.")
                break

            address = self.pc
            op, args, line_no = program[address]
            self.pc += 1
            self.steps += 1

            print(f"\n[{self.steps:03}] PC={address:03} {op} {args}")
            self.execute(op, args)
            print("REGISTERS:", self.registers)

            if step_mode and not self.halted:
                input("Press Enter for the next instruction...")

        print("\n--- FINAL STATE ---")
        print("Registers:", self.registers)
        print("Program counter:", self.pc)
        print("Zero flag:", self.zero)
        print("Memory [0:16]:", self.memory[:16])
        print("Instructions executed:", self.steps)


def interactive_editor():
    print("\n=== MINI COMPUTER EMULATOR ===")
    print("Enter assembly code. Type END on a line to finish.")
    print("Type HELP to see instructions, or EXIT to quit.\n")

    while True:
        command = input("computer> ").strip().upper()

        if command == "EXIT":
            return

        if command == "HELP":
            print(HELP)
            continue

        if command != "EDIT":
            print("Commands: EDIT, HELP, EXIT")
            continue

        print("\n--- ASSEMBLY EDITOR ---")
        print("Enter your program one line at a time.")
        print("Type END on its own line when finished.\n")

        lines = []
        while True:
            line = input(f"{len(lines) + 1:03}> ")
            if line.strip().upper() == "END":
                break
            lines.append(line)

        source = "\n".join(lines)

        try:
            program = Assembler().assemble(source)
        except ValueError as error:
            print("ASSEMBLY ERROR:", error)
            continue

        print(f"\nAssembled {len(program)} instructions.")
        print("1 = Run")
        print("2 = Step through instructions")
        print("3 = Edit again")

        choice = input("Choose: ").strip()

        if choice in ("1", "2"):
            computer = Computer()
            computer.run(program, step_mode=(choice == "2"))
        elif choice == "3":
            continue
        else:
            print("Returning to the command prompt.")


if __name__ == "__main__":
    interactive_editor()
← Back to timeline