Go to file
n loewen 902b218547 (tests) - draw-xy - Change selected pixel to (3, 3) 2023-08-25 11:06:34 +01:00
issues issues - Move 'issues' directory out of 'notes' directory 2023-08-24 20:57:36 +01:00
notes issues - Move 'issues' directory out of 'notes' directory 2023-08-24 20:57:36 +01:00
sketches Feature: Keypad simulation! 2023-08-16 16:23:59 +01:00
test-programs (tests) - draw-xy - Change selected pixel to (3, 3) 2023-08-25 11:06:34 +01:00
assembler.js assembler - Change error handling: Just quit, don't throw a JS error 2023-08-24 16:33:33 +01:00
cpu.js cpu - Add feature: Quit after cycle limit reached 2023-08-24 16:35:21 +01:00
display.js display - Fix: Pretty display was displaying the wrong pixels 2023-08-24 17:06:09 +01:00
jsconfig.json Turn on Jsdoc-based type checking 2023-08-03 16:24:51 +01:00
logging.js assembler/cpu - Add feature: Pass debug info from assembler to cpu, so that cpu can print source line 2023-08-24 13:16:01 +01:00
machine.config.js assembler / machine config - Remove/Change: Remove pointer-to-keypad / Change initial IP 2023-08-24 08:16:56 +01:00
package-lock.json Feature (CPU): Implement a simple single-stepping mode 2023-08-16 13:56:23 +01:00
package.json Feature (CPU): Implement a simple single-stepping mode 2023-08-16 13:56:23 +01:00
readme.md (docs) readme - Change memory map to include initial IP + not-yet-implemented ROM with pointer-to-initial-IP 2023-08-24 08:18:45 +01:00
run-assembler.js assembler/cpu - Add feature: Pass debug info from assembler to cpu, so that cpu can print source line 2023-08-24 13:16:01 +01:00
run-cpu.js assembler/cpu - Add feature: Pass debug info from assembler to cpu, so that cpu can print source line 2023-08-24 13:16:01 +01:00

readme.md

Cardiograph Mark I — simulator for an imaginary computer

Dependencies

  • Node.js
    • readline-sync

Run

Assemble

Hex output:
./run-assembler run source_code.asm

Binary output:
./run-assembler runbin source_code.asm

Verbose debugging output (hex):
./run-assembler debug source_code.asm

Assemble and run

With animated display of screen memory:
./run-cpu run source_code.asm

With verbose debugging output:
./run-cpu debug source_code.asm

With single stepping + pretty-printed display:
./run-cpu step source_code.asm

With single stepping + verbose debugging output:
./run-cpu stepdebug source_code.asm

Registers and Flags

  • A - accumulator
  • IP - instruction pointer (aka program counter)
  • FLAGS - flags: Overflow, Negative, Zero, Carry
    • in machine language, each flag is given a number:
      • O = 3
        N = 2
        Z = 1
        C = 0
    • (bitwise, 0000 = ONZC)

Instruction set

Operations

Hex   Mnem.  Operand      Effect

00    END    (ignored)    Halt CPU
01    STO    literal #    mem[lit#] = A
02    STO    address      mem[mem[addr]] = A
03    LDA    literal #    A = lit#
04    LDA    address      A = addr
05    ADD    literal #    A = A + lit#
06    ADD    address      A = A + mem[addr]
07    SUB    literal #    A = A - lit#
08    SUB    address      A = A - mem[addr]
09    HOP    literal #    If A == lit#, skip next op (IP += 4)
0A    HOP    address      If A == mem[addr], skip next instruction (IP += 4)
0B    JMP    literal #    IP = lit#
0C    JMP    address      IP = mem[addr]
0D    FTG    literal #    Toggle flag, where flag number == lit#
0E    FHP    literal #    Skip next op if flag is set, where flag number == lit#
0F    NOP    (ignored)    None
  • Instructions are two bytes long: one byte for the opcode, one for the operand

Effects on memory, flags, registers

op   mem  flags  IP

END              +2
NOP              +2

STO  w           +2
LDA  r    NZ     +2
ADD       ONZC   +2
SUB       ONZC   +2
HOP              +2/+4
JMP              arg
FTG       ONZC   +2
FHP       ONZC   +2/+4

STO  r,w         +2
LDA  r,r  NZ     +2
ADD  r    ONZC   +2
SUB  r    ONZC   +2
HOP  r           +2/+4
JMP  r           arg
FTG  r    ONZC   +2
FHP  r    ONZC   +2/+4

CPU start-up

When starting up, the CPU executes a JMP $FF.

Put differently: it starts executing instructions at the address contained in $FF.

Cardiograph memory map

  • 00-19 - display (5x5)
  • 1A - pointer to display memory
  • 1B - keypad: value of latest key pressed
  • 1C - reserved for future use (bank switching flag)
  • 1D - initial IP
  • 1D-FE - free
  • FF - ROM (unwriteable) pointer to initial IP (not yet implemented)

Peripherals

Keypad

The value of the latest keypress on a hex keypad is stored at $1B.

The keypad uses the same layout as the COSMAC VIP (and CHIP-8). The CPU simulator maps those keys onto a Qwerty set.

1 2 3 C    1 2 3 4
4 5 6 D    Q W E R
7 8 9 E    A S D F
A 0 B F    Z X C V

  VIP     simulator

Assembly language

ADD $01         ; comments follow a `;`

ADD $FF         ; this is direct addressing
ADD ($CC)       ; this is indirect addressing

END             ; END and NOP don't require operands
                ; (the assembler will fill in a default value of 0)

@subroutine     ; create a label
    ADD $01     ; (it must be on the line before the code it names)
    ADD $02

JMP @subroutine ; use a label as operand
                ; the label will be replaced with
                ; the address of the label

#foo $FF        ; define a constant
                ; (must be defined before it is referenced)

ADD #foo        ; use a constant as an operand

LDA *           ; `*` is a special label referencing the memory address
                ; where the current line will be stored after assembly
  • Hexadecimal numbers are preceded by a $
  • Whitespace is ignored