Go to file
n loewen 12273a6389 assembler - WIP - Continue refactoring everything, in support of 'set the initial IP to assemble to' feature, etc. (Everything is probably broken... but it's much closer) 2023-08-21 19:37:32 +01:00
notes (docs) todos - Add entry about re-ordering flags register 2023-08-21 14:46:43 +01:00
sketches Feature: Keypad simulation! 2023-08-16 16:23:59 +01:00
test-programs assembler - WIP - Start adding a 'set the initial IP to assembler to' feature + Start adding a 'return debug data as well as machine code' feature 2023-08-21 16:08:58 +01:00
assembler.js assembler - WIP - Continue refactoring everything, in support of 'set the initial IP to assemble to' feature, etc. (Everything is probably broken... but it's much closer) 2023-08-21 19:37:32 +01:00
cpu.js Feature: Keypad simulation! 2023-08-16 16:23:59 +01:00
display.js Merge branch '5x5-display' 2023-08-21 14:38:02 +01:00
jsconfig.json Turn on Jsdoc-based type checking 2023-08-03 16:24:51 +01:00
logging.js Feature: WIP: Replace CHP and CFC instructions with FHP and FTG (carry flag is implemented, other flags are not) 2023-08-15 12:04:48 +01:00
machine.config.js Feature: Keypad simulation! 2023-08-16 16:23:59 +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 - Fix keypad section, updating keypad address and removing pointer-to-keypad 2023-08-21 14:47:56 +01:00
run-assembler.js Feature: assembler output in binary 2023-08-10 10:04:18 +01:00
run-cpu.js Docs: Update todos re: invoking the cpu/assembler; move notes on this from `run-cpu.js` to `todo.md` 2023-08-16 16:36:01 +01:00
scratch.js assembler - WIP - Start adding a 'set the initial IP to assembler to' feature + Start adding a 'return debug data as well as machine code' feature 2023-08-21 16:08:58 +01:00

readme.md

Cardiograph Mark I — simulator for a paper 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

Instruction set

00   END
01   STO lit#   ; store ... mem[lit#] <- A
02   STO addr   ; store ... mem[mem[addr]] <- A
03   LDA lit#   ; load  ... A <- lit#
04   LDA addr   ; load  ... A <- mem[addr]
05   ADD lit#   ; add   ... A <- A + lit#      ... and un/set carry flag
06   ADD addr   ; add   ... A <- A + mem[addr] ... and un/set carry flag
07   SUB lit#   ; sub   ... A <- A - lit#      ... and un/set carry flag
08   SUB addr   ; sub   ... A <- A - mem[addr] ... and un/set carry flag
09   HOP lit#   ; hop   ... skip next instruction if A == lit# ... when true: IP <- PC + 4
0A   HOP addr   ; hop   ... skip next instruction if A == addr ... when true: IP <- PC + 4
0B   JMP lit#   ; jump  ... IP <- lit#
0C   JMP addr   ; jump  ... IP <- addr
0D   FTG lit#   ; toggle flag by number (see details below)
0E   FHP lit#   ; flag hop ... skip next instruction if flag is set ... when true: IP <- PC + 4
0F   NOP ————   ; no operation
  • Instructions are two bytes long: one byte for the opcode, one for the operand

Registers and Flags

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

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-FF - free

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