Skip to content

Latest commit

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

The Byte Data Processor 1 (BDP-1)

The BDP-1 is a simple 8-bit learning computer inspired by the Little Man Computer.

It is designed to complement the MTMC-16 as a simpler introduction to computing.

Architecture

  • 8 bit words
  • 4 general registers: A, B, C, D
  • 256 bytes of memory
  • 16 x 16 display, 8-bit color (RGB332)

Register conventions

  • A - accumulator: destination of RMATH/RLOGIC; tested by JZ/JP/JN; result register for WINT/RINT/RAND
  • B, C - general purpose, PLOT instruction uses as x and y coordinates (masked to 4 bits)
  • D - general purpose, PLOT instruction uses as color

Instruction Set

  • Top 4-bit nibble is the instruction type
  • Bottom nibble is op code or args
  • The Most Significant Bit (MSB) of the top nibble distinguishes single-word (0xxx) from double-word (1xxx) instructions
  • The assembler uses a unified MOV dest, src x86-style syntax (Intel order):
    • Brackets mean memory access
    • Bare names/numbers are immediate values
TypeTopOpAssembly formSizeDescription
SYS00000000HALTsinglehalts computer
SYS00000001WINTsinglewrites A to standard out as an unsigned integer
SYS00000010RINTsinglereads standard in to A as an unsigned integer
SYS000010RRRAND RRsingleplaces a random number in register RR
SYS00001111NOOPsingleno operation
GFX00010000CLEARsingleresets graphics to blank (all 0)
GFX00010001PLOTsinglesets pixel at position B, C to color in D
MOV0010SSDDMOV DD, SSsingleDD := SS (register-to-register copy)
MOV0011PPDDMOV DD, [PP]singleDD := M[PP] (indirect load via pointer in PP)
MOV0100PPSSMOV [PP], SSsingleM[PP] := SS (indirect store via pointer in PP)
RMATH010100RRADD A, RRsingleA += RR (accumulator add)
RMATH010101RRSUB A, RRsingleA -= RR
RMATH010110RRMUL A, RRsingleA *= RR
RMATH010111RRDIV A, RRsingleA /= RR (integer; div by 0 -> 0)
RUNARY011000RRINC RRsingleRR += 1
RUNARY011001RRDEC RRsingleRR -= 1
RUNARY011010RRNEG RRsingleRR := -RR (two's complement)
RUNARY011011RRZERO RRsingleRR := 0
RLOGIC011100RRAND A, RRsingleA &= RR
RLOGIC011101RROR A, RRsingleA |= RR
RLOGIC011110RRXOR A, RRsingleA ^= RR
RLOGIC011111RRSHL A, RRsingleA <<= RR (shift left, fills 0)
MEM100000RRMOV RR, [addr]doubleRR := M[addr]
MEM100001RRMOV RR, immdoubleRR := imm (the second byte is the literal value)
MEM100010RRMOV [addr], RRdoubleM[addr] := RR
MMATH100100RRADD RR, [addr]doubleRR += M[addr]
MMATH100101RRSUB RR, [addr]doubleRR -= M[addr]
MMATH100110RRMUL RR, [addr]doubleRR *= M[addr]
MMATH100111RRDIV RR, [addr]doubleRR /= M[addr] (integer; div by 0 -> 0)
JUMP10100000JMP addrdoublePC := addr
JUMP10100001JZ addrdoublejump if A == 0
JUMP10100010JP addrdoublejump if A > 0 (high bit clear, value non-zero)
JUMP10100011JN addrdoublejump if A < 0 (high bit set)
JUMP10100100JSR addrdoublewrites return address into M[addr], then jumps to addr+1
JUMP10100101JI addrdoublePC := M[addr] (indirect jump; serves as RET when paired with JSR)
LOGIC101100RRAND RR, [addr]doubleRR &= M[addr]
LOGIC101101RROR RR, [addr]doubleRR |= M[addr]
LOGIC101110RRXOR RR, [addr]doubleRR ^= M[addr]
LOGIC101111RRSHL RR, [addr]doubleRR <<= M[addr] (shift left, fills 0)

Subroutine convention

The BDP uses a PDP style for invoking sub-routines:

  • JSR slot writes the return address into M[slot] and jumps to slot+1
  • The function body lives at slot+1
  • Return with JI slot (indirect jump through the saved address)
  • NO STACK: not re-entrant!
 MOV A, 5
JSR double ; M[double] := return addr; PC := double+1
WINT
HALT
double: SW 0 ; return slot; body starts at the next byte
MOV [scratch], A
ADD A, [scratch]
JI double ; return
scratch: SW 0

Programming

The BDP-1 can be programmed three ways, from lowest-level to highest:

  • Punch cards: click holes to toggle individual bits of each byte
  • Assembly: mnemonics and labels, run through the built-in assembler
  • ByteTran: a small Fortran-flavored HLL that compiles to BDP-1 assembly

Each is documented below.

Punch Cards

The CARD tab presents a vertical, 32-byte punch card.

Each row has eight clickable holes (bit 7 on the left, bit 0 on the right)

Clicking a hole flips the corresponding bit.

You can load the program into memory using the "Load Card" button below the card.

Note that this is not how punch card programming worked in the era we mostly think of: only very early punch card systems used raw binary encodings.

Assembly

The ASM tab is a plain text editor that runs through a two-pass assembler.

Click ASSEMBLE & LOAD to assemble the source & load In it into memory starting at 0x00. A

The EXAMPLES dropdown ships several short programs (random pixels, count loop, color sweep, JSR demo, indirect array sum, XOR moire).

ASM Guide

Write one instruction per line. Operands are separated by spaces or commas. Mnemonics and register names are case-insensitive.

 MOV A, 5 ; load immediate
MOV B, [count] ; load from memory
ADD A, B ; accumulator add (dst must be A)
MOV [count], A ; store back
HALT
count: SW 0

Operands

The same mnemonic (MOV, ADD, SUB, ...) accepts multiple operand shapes: the assembler picks the right encoding from the syntax

OperandMeaning
A/B/C/Da register
[A] etc.memory at the address held in that register (indirect)
[label] / [42] / [0x2A]memory at the given address (absolute)
label / 42 / 0x2A / 0b101 / 'X'immediate value (or address, for jumps)

Brackets mean "memory access."

Bare names and numbers are immediate (for data ops) or jump targets (for JMP/JZ/JP/JN/JSR/JI).

Numeric literals can be decimal, 0x-prefixed hex or 0b-prefixed binary.

Assembler directives

  • label: defines a label at the current address
  • SW value [, value ...] emits one raw byte per value (decimal, hex, binary, char, or a label)
  • ; starts a comment to end of line

Labels are resolved during pass 2, so forward references (e.g. JMP done before the done: line) work.

ByteTran

ByteTran is a Fortran-flavored high level language that compiles to BDP-1 assembly. It is uppercase, integer-only & whitespace-sensitive.

The ByteTran tab has a source editor on top and a read-only view of the generated assembly underneath that updates on every keystroke.

This shows how high level language constructs translate into assembly instructions.

Click COMPILE & LOAD to assemble that output and run it.

Grammar

program = { statement }
statement = IDENT '=' expr ! assignment
| 'WRITE' expr
| 'DO' 'WHILE' expr { statement } 'END'
| 'IF' expr { statement } [ 'ELSE' { statement } ] 'END'
expr = 'READ' | additive [ ('>='|'==') additive ]
additive = primary [ ('+'|'-') primary ]
primary = IDENT | NUMBER | 'TRUE' | 'FALSE'
comment = '!' to end of line

Example

! Fibonacci - read N, print fib(N)
N = READ
A = 0
B = 1
DO WHILE N >= 1
T = A + B
A = B
B = T
N = N - 1
END
WRITE A

Limitations

  • Expressions do not nest: a + b + c is illegal. At most one additive operator per expression, optionally wrapped by one comparison (so a - b >= c is allowed).
  • All arithmetic is 8-bit and wraps modulo 256.

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages