{"id":26269444,"url":"https://github.com/dominikoetiker/virtual_cpu_python","last_synced_at":"2026-05-14T13:34:18.287Z","repository":{"id":280434019,"uuid":"941890809","full_name":"dominikoetiker/virtual_cpu_python","owner":"dominikoetiker","description":"project to simulate a cpu in python","archived":false,"fork":false,"pushed_at":"2025-03-12T22:33:36.000Z","size":12,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-12T23:24:59.366Z","etag":null,"topics":["asm","assembly","cpu","cpu-emulator","educational-project","emulator","input-output","learning","memory-management","python3","virtual-cpu","virtual-machine","virtualization"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dominikoetiker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-03T08:20:25.000Z","updated_at":"2025-03-12T22:33:39.000Z","dependencies_parsed_at":"2025-03-03T12:42:50.984Z","dependency_job_id":null,"html_url":"https://github.com/dominikoetiker/virtual_cpu_python","commit_stats":null,"previous_names":["dominikoetiker/virtual_cpu_python"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominikoetiker%2Fvirtual_cpu_python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominikoetiker%2Fvirtual_cpu_python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominikoetiker%2Fvirtual_cpu_python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominikoetiker%2Fvirtual_cpu_python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dominikoetiker","download_url":"https://codeload.github.com/dominikoetiker/virtual_cpu_python/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243526942,"owners_count":20305115,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asm","assembly","cpu","cpu-emulator","educational-project","emulator","input-output","learning","memory-management","python3","virtual-cpu","virtual-machine","virtualization"],"created_at":"2025-03-14T05:14:13.866Z","updated_at":"2025-10-29T16:04:00.454Z","avatar_url":"https://github.com/dominikoetiker.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Virtual CPU Python\n\nA Python-based CPU simulator to understand the basic components and operations of a central processing unit.\n\n## Project Overview\n\nThis project implements a virtual CPU in Python to simulate the basic operations and components of a computer's central processing unit.\nThe goal was to understand how CPUs work at a fundamental level by creating a working model with registers, memory, an arithmetic logic unit, a control unit, and I/O capabilities.\n\nThe CPU currently can execute programs provided as bytearrays.\nThe next planned feature is an assembler to translate human-readable assembly code into the bytecode format.\n\n## Architecture\n\nThe virtual CPU implements a simplified architecture with the following components:\n\n### Controllers\n\n- **Arithmetic Logic Unit (ALU)**: Handles arithmetic and logical operations\n- **Control Unit (CU)**: Manages the fetch-decode-execute cycle\n- **Memory Controller**: Manages access to RAM\n- **I/O Controller**: Handles input and output operations\n- **Instruction Unit**: Manages program flow and control instructions\n\n### Registers\n\n- **General Purpose Registers**: R0, R1\n- **Output Register**: R2\n- **Link Register**: R3 (stores return addresses)\n- **Memory Byte Register**: R4\n- **Program Counter**: R5\n- **Program Base Address Register**: R6 (holds the base address of the current program)\n\n### Flags\n\n- **Z**: Zero flag - Set when a result is zero, used for conditional operations\n\n### Memory System\n\n- RAM with configurable size (default: 1024 bytes)\n- Support for address-based memory access\n\n### Interrupt System\n\nThe CPU now features a complete interrupt handling system:\n\n- **Interrupt Controller**: Manages interrupt requests and context switching\n- **Socket-based Interface**: Allows external programs to trigger interrupts while the CPU is running\n- **Context Preservation**: Automatically saves and restores CPU state during interrupts\n- **Support for Multiple Programs**: Load and execute multiple programs without rebooting the CPU\n\n#### Interrupt Operations\n\n| Command | Description                                       |\n| ------- | ------------------------------------------------- |\n| 0x00    | Load a program into memory at a specified address |\n| 0x01    | Execute a program at a specified address          |\n\n## Bytecode Format\n\n### Instruction Set\n\n| Opcode                    | Mnemonic | Assembly instruction Format | Description                                              | Flags Affected |\n| ------------------------- | -------- | --------------------------- | -------------------------------------------------------- | -------------- |\n| **Control Operations**    |\n| 0x00                      | NOP      | `NOP`                       | No operation, processor continues to next instruction    | None           |\n| 0x01                      | HLT      | `HLT`                       | Halt execution, go to idle state                         | None           |\n| **Data Operations**       |\n| 0x02                      | MOV      | `MOV Rd, Op2`               | Copy Op2 (register or value) into destination register   | None           |\n| **Branch Operations**     |\n| 0x03                      | BEQ      | `BEQ [addr]`                | Branch to address if Z flag is set (result was zero)     | None           |\n| 0x04                      | BNE      | `BNE [addr]`                | Branch to address if Z flag is not set (result non-zero) | None           |\n| 0x05                      | B        | `B [addr]`                  | Branch unconditionally to address                        | None           |\n| 0x06                      | BL       | `BL [addr]`                 | Branch to address and store return address in R3         | None           |\n| 0x07                      | BX       | `BX`                        | Branch to address stored in link register (R3)           | None           |\n| **Arithmetic Operations** |\n| 0x08                      | ADD      | `ADD Rd, Rn, Op2`           | Rd = Rn + Op2                                            | Z              |\n| 0x09                      | SUB      | `SUB Rd, Rn, Op2`           | Rd = Rn - Op2                                            | Z              |\n| 0x0A                      | MUL      | `MUL Rd, Rn, Op2`           | Rd = Rn \\* Op2                                           | Z              |\n| 0x0B                      | DIV      | `DIV Rd, Rn, Op2`           | Rd = Rn // Op2 (integer division)                        | Z              |\n| 0x0C                      | MOD      | `MOD Rd, Rn, Op2`           | Rd = Rn % Op2 (modulo)                                   | Z              |\n| **Logical Operations**    |\n| 0x0D                      | AND      | `AND Rd, Rn, Op2`           | Rd = Rn \u0026 Op2 (bitwise AND)                              | Z              |\n| 0x0E                      | ORR      | `ORR Rd, Rn, Op2`           | Rd = Rn \\| Op2 (bitwise OR)                              | Z              |\n| 0x0F                      | XOR      | `XOR Rd, Rn, Op2`           | Rd = Rn ^ Op2 (bitwise XOR)                              | Z              |\n| 0x10                      | NOT      | `NOT Rd, Op2`               | Rd = ~Op2 (bitwise NOT)                                  | Z              |\n| **Shift Operations**      |\n| 0x11                      | LSL      | `LSL Rd, Rn, Op2`           | Rd = Rn \u003c\u003c Op2 (logical shift left)                      | Z              |\n| 0x12                      | LSR      | `LSR Rd, Rn, Op2`           | Rd = Rn \u003e\u003e Op2 (logical shift right)                     | Z              |\n| **Compare Operations**    |\n| 0x13                      | CMP      | `CMP Rn, Op2`               | Compare Rn with Op2 and set Z flag accordingly           | Z              |\n| **Memory Operations**     |\n| 0x14                      | LDR      | `LDR Rd, [addr]`            | Load value from memory address into Rd                   | None           |\n| 0x15                      | STR      | `STR Rd, [addr]`            | Store value from Rd into memory address                  | None           |\n| **I/O Operations**        |\n| 0x16                      | INP      | `INP Rd`                    | Read input from user and store in Rd                     | None           |\n| 0x17                      | OUT      | `OUT Rd`                    | Output value from Rd to console                          | None           |\n| 0x18                      | OUTC     | `OUTC Rd`                   | Output character from Rd to console                      | None           |\n| **Interrupt Operations**  |\n| 0xFF                      | IRET     | `IRET`                      | Return from interrupt, restoring previous CPU state      | None           |\n\nWhere:\n\n- `Rd` = Destination register\n- `Rn` = First operand register\n- `Op2` = Second operand (register or immediate value)\n- `[addr]` = Memory address (register or immediate value or label -\u003e label is transformed by assembler to immediate value in Bytecode)\n- `Z` = Zero flag (set when result is zero)\n\n### Operand Types\n\n| Code | Type     | Size (bytes) |\n| ---- | -------- | ------------ |\n| 0x00 | register | 1            |\n| 0x01 | value    | 2            |\n\n### Register Codes\n\n| Code | Register | Description                   |\n| ---- | -------- | ----------------------------- |\n| 0x00 | R0       | General Purpose Register 0    |\n| 0x01 | R1       | General Purpose Register 1    |\n| 0x02 | R2       | Output Register               |\n| 0x03 | R3       | Link Register                 |\n| 0x04 | R4       | Memory Byte Register          |\n| 0x05 | R5       | Program Counter               |\n| 0x06 | R6       | Program Base Address Register |\n\n### Instruction Format\n\nEach instruction is represented as a sequence of bytes in the following format:\n\n```\nOpcode [LastOperandType, Oberand1 [Operand2 [Operand3 ...]]]\n```\n\nWhere:\n\n- **Opcode**: 1 byte\n- **Last Operand Type**: 1 byte\n- **Operands**: 0-n bytes (depending on the instruction), using little-endian byte order\n\n**Relative Addressing**:\nThe CPU supports relative addressing for branch instructions. The address is calculated as an offset from the current Program Base Address Register (R6).\n\n## Usage\n\nBest way to run and interact with the CPU is with two terminal windows. In one terminal, run the CPU simulator, and in the other, use the provided scripts to load and execute programs. You can for example use tmux to split the terminal window or open two separate terminal windows.\n\n### Running the CPU\n\nTo run the CPU simulator, execute the following command:\n\n```bash\npython main.py\n```\n\n### Dynamic Program Loading\n\nPrograms can now be loaded and executed while the CPU is running using the provided scripts:\n\n```bash\n# Load a program into memory\n./program_loader.sh \u003cprogram_file.mem\u003e \u003cmemory_address\u003e\n\n# Execute a program at a specified address\n./program_starter.sh \u003cmemory_address\u003e\n```\n\n**Note**: The memory address for programs should be equal or greater than 0x0A (10 in decimal). The Addresses 0x00 to 0x09 are reserved for the CPU's idle state.\n\nFor example:\n\n```bash\n# Load Hello World program at address 0x0A\n./program_loader.sh hello_world.mem 0x0A\n\n# Run the Hello World program\n./program_starter.sh 0x0A\n\n# Load Fibonacci sequence generator at address 0xA1\n./program_loader.sh fibonacci.mem 0xA1\n\n# Run the Fibonacci sequence generator\n./program_starter.sh 0xA1\n```\n\n**Note**: Make the scripts executable before running them:\n\n```bash\nchmod +x program_loader.sh program_starter.sh\n```\n\n## Example Programs\n\nHere are some example programs written as commented bytearrays that can be loaded and executed by the CPU.\n\n**Note**: To load these programs dynamically, you need to put the hex values without commas and without the comments, just separated by spaces and/or new lines (like this: `0x02 0x01 0x00 0x48 0x00 0x18 0x00 0x00 ...`), in a file with the `.mem` extension (using the extension is optional, but it helps to identify the file type).\n\n\u003cdetails\u003e\n\u003csummary\u003eHello World\u003c/summary\u003e\n\nThis program outputs \"Hello World\" to the console.\n\n```python\nhello_world = bytearray([\n    # Hello World program\n    0x02, 0x01, 0x00, 0x48, 0x00,  # MOV R0, 72 (H)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x65, 0x00,  # MOV R0, 101 (e)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x6c, 0x00,  # MOV R0, 108 (l)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x6c, 0x00,  # MOV R0, 108 (l)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x6f, 0x00,  # MOV R0, 111 (o)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x20, 0x00,  # MOV R0, 32 (space)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x57, 0x00,  # MOV R0, 87 (W)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x6f, 0x00,  # MOV R0, 111 (o)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x72, 0x00,  # MOV R0, 114 (r)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x6c, 0x00,  # MOV R0, 108 (l)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x64, 0x00,  # MOV R0, 100 (d)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x0a, 0x00,  # MOV R0, 10 (LF)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0xFF,                          # IRET\n])\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eAdd two numbers\u003c/summary\u003e\n\nThis program adds two numbers and outputs the result.\n\n```python\n add_two_numbers = bytearray(\n     [\n         # Example: Adding two numbers and outputting the result\n         0x02, 0x01, 0x00, 0x05, 0x00,  # MOV R0, 5 # fmt: skip\n         0x02, 0x01, 0x01, 0x03, 0x00,  # MOV R1, 3 # fmt: skip\n         0x08, 0x00, 0x00, 0x00, 0x01,  # ADD R0, R0, R1 # fmt: skip\n         0x17, 0x00, 0x00,  # OUT R0 # fmt: skip\n         0xFF,  # IRET # fmt: skip\n     ]\n )\n\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eAdding numbers with user input\u003c/summary\u003e\n\nThis program adds two numbers, gets a new number from the user, adds it to the sum, and outputs the result.\n\n```python\nexample_program_1 = bytearray(\n    [\n        # Example: Adding two numbers, getting a new number from the user, adding it to the sum and outputting the result\n        0x02,  # PC: 0x0000: MOV\n        0x01,  # PC: 0x0001: last_operand_type (value)\n        0x00,  # PC: 0x0002: operand_1 (register 0)\n        0x01,  # PC: 0x0003: second byte of value 1\n        0x00,  # PC: 0x0004: first byte of value 1\n        0x02,  # PC: 0x0005: MOV\n        0x01,  # PC: 0x0006: last_operand_type (value)\n        0x01,  # PC: 0x0007: operand_1 (register 1)\n        0x02,  # PC: 0x0008: second byte of value 2\n        0x00,  # PC: 0x0009: first byte of value 2\n        0x08,  # PC: 0x000a: ADD\n        0x00,  # PC: 0x000b: last_operand_type (register)\n        0x00,  # PC: 0x000c: operand_1 (result register: register 0)\n        0x00,  # PC: 0x000d: operand_2 (summand 1: register 0)\n        0x01,  # PC: 0x000e: operand_3 (summand 2: register 1)\n        0x16,  # PC: 0x000f: INP\n        0x00,  # PC: 0x0010: last_operand_type (register)\n        0x01,  # PC: 0x0011: operand_1 (register 1)\n        0x08,  # PC: 0x0012: ADD\n        0x00,  # PC: 0x0013: last_operand_type (register)\n        0x00,  # PC: 0x0014: operand_1 (result register: register 0)\n        0x00,  # PC: 0x0015: operand_2 (summand 1: register 0)\n        0x01,  # PC: 0x0016: operand_3 (summand 2: register 1)\n        0x17,  # PC: 0x0017: OUT\n        0x00,  # PC: 0x0018: last_operand_type (register)\n        0x00,  # PC: 0x0019: operand_1 (register 0)\n        0xFF,  # PC: 0x001a: IRET\n    ]\n)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCheck if one number is greater than the other\u003c/summary\u003e\n\nThis program checks if a number is greater than another and outputs the result.\n\n```python\nis_greater_than: bytearray = bytearray(\n    [\n        # Example: check if a is \u003e than b\n        # INP R0 (a)\n        0x16, # PC: 0x0000: INP\n        0x00, # PC: 0x0001: last_operand_type (register)\n        0x00, # PC: 0x0002: operand_1 (register 0)\n\n        # INP R1 (b)\n        0x16, # PC: 0x0003: INP\n        0x00, # PC: 0x0004: last_operand_type (register)\n        0x01, # PC: 0x0005: operand_1 (register 1)\n\n        # SUB R0, R0, R1 (R0 = R0 - R1) (a - b)\n        0x09, # PC: 0x0006: SUB\n        0x00, # PC: 0x0007: last_operand_type (register)\n        0x00, # PC: 0x0008: operand_1 (register 0)\n        0x00, # PC: 0x0009: operand_2 (register 0)\n        0x01, # PC: 0x000a: operand_3 (register 1)\n\n        # AND R0, R0, 0b1000 0000 0000 0000 (R0 = R0 \u0026 0b1000 0000 0000 0000) (check if the most significant bit of R0 is set to 1)\n        0x0D, # PC: 0x000b: AND\n        0x01, # PC: 0x000c: last_operand_type (value)\n        0x00, # PC: 0x000d: operand_1 (register 0)\n        0x00, # PC: 0x000e: operand_2 (register 0)\n        0x00, # PC: 0x000f: second byte of value 0b1000 0000 0000 0000\n        0x80, # PC: 0x0010: first byte of value 0b1000 0000 0000 0000\n\n        # LSR R0, R0, 15 (R0 = R0 \u003e\u003e 15) (shift the most significant bit to the least significant bit)\n        0x12, # PC: 0x0011: LSR\n        0x01, # PC: 0x0012: last_operand_type (value)\n        0x00, # PC: 0x0013: operand_1 (register 0)\n        0x00, # PC: 0x0014: operand_2 (register 0)\n        0x0f, # PC: 0x0015: second byte of value 15\n        0x00, # PC: 0x0016: first byte of value 15\n\n        # OUT R0 (if output is 1, a \u003c b, if output is 0, a \u003e= b)\n        0x17, # PC: 0x0017: OUT\n        0x00, # PC: 0x0018: last_operand_type (register)\n        0x00, # PC: 0x0019: operand_1 (register 0)\n\n        # IRET\n        0xFF, # PC: 0x001d: IRET\n    ]\n)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eFibonacci sequence generator\u003c/summary\u003e\n\nThis program calculates and outputs the Fibonacci sequence up to a specified maximum value.\n\n```python\nfibonacci: bytearray = bytearray(\n    [\n        # Example: Output all Fibonacci numbers up to user defined limit\n        # set_limit:\n        # INP R0\n        0x16,  # PC: 0x0000: INP\n        0x00,  # PC: 0x0001: last_operand_type (register)\n        0x00,  # PC: 0x0002: operand_1 (register 0)\n        # STR R0, 0x80 (store the limit in memory)\n        0x15,  # PC: 0x0003: STR\n        0x01,  # PC: 0x0004: last_operand_type (value)\n        0x00,  # PC: 0x0005: operand_1 (register 0)\n        0x80,  # PC: 0x0006: second byte of address\n        0x00,  # PC: 0x0007: first byte of address\n        # store_first_two_numbers:\n        # MOV R0, 0\n        0x02,  # PC: 0x0008: MOV\n        0x01,  # PC: 0x0009: last_operand_type (value)\n        0x00,  # PC: 0x000a: operand_1 (register 0)\n        0x00,  # PC: 0x000b: second byte of value 0\n        0x00,  # PC: 0x000c: first byte of value 0\n        # STR R0, 0x82 (store the first number in memory)\n        0x15,  # PC: 0x000d: STR\n        0x01,  # PC: 0x000e: last_operand_type (value)\n        0x00,  # PC: 0x000f: operand_1 (register 0)\n        0x82,  # PC: 0x0010: second byte of address\n        0x00,  # PC: 0x0011: first byte of address\n        # BL 0x2c (is_current_number_greater_than_limit)\n        0x06,  # PC: 0x0012: BL\n        0x01,  # PC: 0x0013: last_operand_type (value)\n        0x2C,  # PC: 0x0014: second byte of address (is_current_number_greater_than_limit)\n        0x00,  # PC: 0x0015: first byte of address (is_current_number_greater_than_limit)\n        # LDR R0, 0x82 (load the first number from memory)\n        0x14,  # PC: 0x0016: LDR\n        0x01,  # PC: 0x0017: last_operand_type (value)\n        0x00,  # PC: 0x0018: operand_1 (register 0)\n        0x82,  # PC: 0x0019: second byte of address\n        0x00,  # PC: 0x001a: first byte of address\n        # OUT R0\n        0x17,  # PC: 0x001b: OUT\n        0x00,  # PC: 0x001c: last_operand_type (register)\n        0x00,  # PC: 0x001d: operand_1 (register 0)\n        # MOV R0, 1\n        0x02,  # PC: 0x001e: MOV\n        0x01,  # PC: 0x001f: last_operand_type (value)\n        0x00,  # PC: 0x0020: operand_1 (register 0)\n        0x01,  # PC: 0x0021: second byte of value 1\n        0x00,  # PC: 0x0022: first byte of value 1\n        # STR R0, 0x84 (store the second number in memory)\n        0x15,  # PC: 0x0023: STR\n        0x01,  # PC: 0x0024: last_operand_type (value)\n        0x00,  # PC: 0x0025: operand_1 (register 0)\n        0x84,  # PC: 0x0026: second byte of address\n        0x00,  # PC: 0x0027: first byte of address\n        # B 0x47 (print_fibonacci_loop)\n        0x05,  # PC: 0x0028: B\n        0x01,  # PC: 0x0029: last_operand_type (value)\n        0x47,  # PC: 0x002a: second byte of address (print_fibonacci_loop)\n        0x00,  # PC: 0x002b: first byte of address (print_fibonacci_loop)\n        # is_current_number_greater_than_limit:\n        # LDR R1, 0x80 (load the limit from memory)\n        0x14,  # PC: 0x002c: LDR\n        0x01,  # PC: 0x002d: last_operand_type (value)\n        0x01,  # PC: 0x002e: operand_1 (register 1)\n        0x80,  # PC: 0x002f: second byte of address\n        0x00,  # PC: 0x0030: first byte of address\n        # SUB R0, R0, R1 (R0 = R0 - R1) (current_number - limit)\n        0x09,  # PC: 0x0031: SUB\n        0x00,  # PC: 0x0032: last_operand_type (register)\n        0x00,  # PC: 0x0033: operand_1 (register 0)\n        0x00,  # PC: 0x0034: operand_2 (register 0)\n        0x01,  # PC: 0x0035: operand_3 (register 1)\n        # AND R0, R0, 0b1000 0000 0000 0000 (R0 = R0 \u0026 0b1000 0000 0000 0000) (extract the most significant bit)\n        0x0D,  # PC: 0x0036: AND\n        0x01,  # PC: 0x0037: last_operand_type (value)\n        0x00,  # PC: 0x0038: operand_1 (register 0)\n        0x00,  # PC: 0x0039: operand_2 (register 0)\n        0x00,  # PC: 0x003a: second byte of value 0b1000 0000 0000 0000\n        0x80,  # PC: 0x003b: first byte of value 0b1000 0000 0000 0000\n        # CMP R0, 0 (compare the result with 0. If the most significant bit is 1 (sign), the current number is less than the limit)\n        0x13,  # PC: 0x003c: CMP\n        0x01,  # PC: 0x003d: last_operand_type (value)\n        0x00,  # PC: 0x003e: operand_1 (register 0)\n        0x00,  # PC: 0x003f: second byte of value 0\n        0x00,  # PC: 0x0040: first byte of value 0\n        # BNE 0x46 (if the current number is not greater than the limit, jump to jmp_back)\n        0x04,  # PC: 0x0041: BNE\n        0x01,  # PC: 0x0042: last_operand_type (value)\n        0x46,  # PC: 0x0043: second byte of address (jmp_back)\n        0x00,  # PC: 0x0044: first byte of address (jmp_back)\n        # IRET (if the current number is greater than the limit, halt the program)\n        0xFF,  # PC: 0x0045: IRET\n        # jmp_back:\n        # BX (jump back, where came from)\n        0x07,  # PC: 0x0046: BX\n        # print_fibonacci_loop:\n        # LDR R0, 0x82 (load the first number from memory)\n        0x14,  # PC: 0x0047: LDR\n        0x01,  # PC: 0x0048: last_operand_type (value)\n        0x00,  # PC: 0x0049: operand_1 (register 0)\n        0x82,  # PC: 0x004a: second byte of address\n        0x00,  # PC: 0x004b: first byte of address\n        # LDR R1, 0x84 (load the second number from memory)\n        0x14,  # PC: 0x004c: LDR\n        0x01,  # PC: 0x004d: last_operand_type (value)\n        0x01,  # PC: 0x004e: operand_1 (register 1)\n        0x84,  # PC: 0x004f: second byte of address\n        0x00,  # PC: 0x0050: first byte of address\n        # STR R0, 0x84 (store the first number in memory)\n        0x15,  # PC: 0x0051: STR\n        0x01,  # PC: 0x0052: last_operand_type (value)\n        0x00,  # PC: 0x0053: operand_1 (register 0)\n        0x84,  # PC: 0x0054: second byte of address\n        0x00,  # PC: 0x0055: first byte of address\n        # ADD R0, R0, R1 (R0 = R0 + R1) (current_number = first_number + second_number)\n        0x08,  # PC: 0x0056: ADD\n        0x00,  # PC: 0x0057: last_operand_type (register)\n        0x00,  # PC: 0x0058: operand_1 (register 0)\n        0x00,  # PC: 0x0059: operand_2 (register 0)\n        0x01,  # PC: 0x005a: operand_3 (register 1)\n        # STR R0, 0x82 (store the current number in memory)\n        0x15,  # PC: 0x005b: STR\n        0x01,  # PC: 0x005c: last_operand_type (value)\n        0x00,  # PC: 0x005d: operand_1 (register 0)\n        0x82,  # PC: 0x005e: second byte of address\n        0x00,  # PC: 0x005f: first byte of address\n        # BL 0x2c (is_current_number_greater_than_limit)\n        0x06,  # PC: 0x0060: BL\n        0x01,  # PC: 0x0061: last_operand_type (value)\n        0x2C,  # PC: 0x0062: second byte of address (is_current_number_greater_than_limit)\n        0x00,  # PC: 0x0063: first byte of address (is_current_number_greater_than_limit)\n        # LDR R0, 0x82 (load the current number from memory)\n        0x14,  # PC: 0x0064: LDR\n        0x01,  # PC: 0x0065: last_operand_type (value)\n        0x00,  # PC: 0x0066: operand_1 (register 0)\n        0x82,  # PC: 0x0067: second byte of address\n        0x00,  # PC: 0x0068: first byte of address\n        # OUT R0\n        0x17,  # PC: 0x0069: OUT\n        0x00,  # PC: 0x006a: last_operand_type (register)\n        0x00,  # PC: 0x006b: operand_1 (register 0)\n        # B 0x47 (print_fibonacci_loop)\n        0x05,  # PC: 0x006c: B\n        0x01,  # PC: 0x006d: last_operand_type (value)\n        0x47,  # PC: 0x006e: second byte of address (print_fibonacci_loop)\n        0x00,  # PC: 0x006f: first byte of address (print_fibonacci_loop)\n    ]\n)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCooperative Multitasking: Two programs jumping from one to the other\u003c/summary\u003e\n\nThis program needs to load to address 0x0A\n\n```python\nprint_a: bytearray = bytearray(\n  [\n    0x02, 0x01, 0x00, 0x41, 0x00,  # MOV R0, 65 (A)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x0a, 0x00,  # MOV R0, 10 (LF)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x05, 0x01, 0x96, 0x00,        # B 0x96 (0xA0 minus relative address(Start address of programm a))\n  ]\n)\n```\n\nThis program needs to be loaded to address 0xA0\n\n```python\nprint_b: bytearray = bytearray(\n  [\n    0x02, 0x01, 0x00, 0x42, 0x00,  # MOV R0, 66 (B)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x02, 0x01, 0x00, 0x0a, 0x00,  # MOV R0, 10 (LF)\n    0x18, 0x00, 0x00,              # OUTC R0\n    0x05, 0x01, 0x00, 0x00,        # B 0x00 (0x0A minus relative address (Start address of program a))\n  ]\n)\n```\n\n\u003c/details\u003e\n\n## Future Development\n\n1. ✅ **Loader**: Implemented loader to load programs from files\n2. ✅ **Interrupt Handling**: Implemented a complete interrupt system\n3. **Assembler**: Create a tool to translate assembly language into bytecode\n\n## Contributing\n\nContributions to this project are welcome! Whether you're a beginner or experienced developer, your input is valuable. Here are some ways to contribute:\n\n- **Bug reports**: If you find an issue, please create a GitHub issue\n- **Feature suggestions**: Have ideas for improvements? Let me know!\n- **Code contributions**: Pull requests for new features or bug fixes are welcome\n- **Documentation**: Help improve or extend the documentation\n- **Educational feedback**: As this is a learning project, I appreciate feedback on the architecture and design\n\n## License\n\nThis project is available under the MIT License. See the LICENSE file for details.\n\n## Acknowledgments\n\nThis project was created as a personal learning exercise for me to understand CPU architecture.\nIt's meant to be educational rather than a production-ready CPU emulator.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominikoetiker%2Fvirtual_cpu_python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdominikoetiker%2Fvirtual_cpu_python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominikoetiker%2Fvirtual_cpu_python/lists"}