Go to file
n loewen 24a3bc60da Name it "Cardiograph"! 2023-08-10 11:43:11 +01:00
notes Move brainstorming about possible features from readme to dev note 2023-08-10 11:42:36 +01:00
sketches Move early sketches to 'sketches' folder 2023-08-07 10:39:28 +01:00
test-programs Assembler: always add an END at the end of the output 2023-08-03 15:53:59 +01:00
assembler.js Add JSdoc annotatinos 2023-08-03 16:42:19 +01:00
display.js Add JSdoc annotatinos 2023-08-03 16:42:19 +01:00
jsconfig.json Turn on Jsdoc-based type checking 2023-08-03 16:24:51 +01:00
logging.js Feature: assembler output in binary 2023-08-10 10:04:18 +01:00
machine.config.js Move display memory back to $00 to make programming easy 2023-08-03 08:34:58 +01:00
package-lock.json Install jsdoc and jsdoc-to-markdown 2023-08-03 16:51:42 +01:00
package.json Remove npm scripts: just run it using ./ 2023-08-10 10:07:10 +01:00
readme.md Name it "Cardiograph"! 2023-08-10 11:43:11 +01:00
run-assembler.js Feature: assembler output in binary 2023-08-10 10:04:18 +01:00
run-cpu.js Add shebangs to run-scripts 2023-08-07 11:00:04 +01:00
simulator.js Add JSdoc annotatinos 2023-08-03 16:42:19 +01:00

readme.md

Cardiograph-I — simulator for a paper computer

Dependencies

Node.js

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

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 + 2
0A   HOP addr   ; hop   ... skip next instruction if A == addr ... when true: IP <- PC + 2
0B   JMP lit#   ; jump  ... IP <- lit#
0C   JMP addr   ; jump  ... IP <- addr
0D   CCF ————   ; clear Carry Flag ... CF = 0
0E   CHP ————   ; carry hop ... skip next instruction if Carry Flag is set ... when true: IP <- PC + 2
0F   NOP ————   ; no operation
  • Instructions are two bytes long: one byte for the opcode, one for the argument

Registers and Flags

  • A - accumulator
  • IP - instruction pointer (aka program counter)
  • CF - carry flag

Memory map / Peripherals

  • 00-0F - display (4x4)
  • 10-1F - keypad? (details TBD)
  • 20 - pointer to display memory
  • 21 - pointer to keypad memory
  • 22-2F - reserved for future use / variable storage
  • 30 - initial value for IP
  • 30-FF - free

Assembly language

ADD $01         ; comments follow a `;`

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

END             ; END, CFC, and CHP don't require arguments
                ; (a default value of 0 will be used as their operand)

@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 an argument
                ; 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
  • Hexadecimal numbers are preceded by a $
  • Whitespace is ignored