Give Programs/ one rule: a directory per kind, nothing loose
Five .asm files sat at the top of Programs/ beside six directories, with
nothing to say which a new file should join - and hello.asm, which is the
native assembler's first target and named in sixteen places, looked like a
stray.
Programs/
Examples/ what you read to learn: hello, printHello, inputTest,
replCalculator, and Fibonacci, primeSieve and gameOfLife
as sets of their own
Libraries/ included by name, no entry point of their own
Loader/ loader.asm, and the loadable program it reads
CosmOS/ the system, its applications and its assembler
testPrograms/ what 'make test' drives
Loader/ is the one worth explaining. loader.asm is not a demonstration: it
reads a program off a disk, puts the two pieces where the header asks, and
jumps to the entry. CosmOS grew out of it and does the same thing as one of
its commands. It is kept because backward compatibility with the simplest
version of the system is a standing goal, and it was sitting loose next to
the demos as though it were one.
Programs/loadable/ was a directory holding one file called hello.asm - a
third thing of that name, and the name said nothing about why it was there.
It is Loader/loadable.asm now, beside the loader that reads it.
Every reference moved with them: the makefile's program list, twelve
manifest lines, makedisks.sh, native.sh, and four paths across the README
and both manuals. Verified by deleting both build directories and running
the whole suite from nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
6dbb38b209
commit
ccf4b384e1
@@ -0,0 +1,77 @@
|
||||
; A Fibonacci number generating program that uses two bytes to store the value.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
start:
|
||||
; Swap ValueB and ValueA.
|
||||
; First, store ValueA on the stack.
|
||||
SETD ValueA
|
||||
LDA
|
||||
PSHA
|
||||
INCD
|
||||
LDA
|
||||
PSHA
|
||||
; Now copy ValueB into AB.
|
||||
SETD ValueB
|
||||
LDA ; High byte
|
||||
INCD
|
||||
LDB ; Low byte
|
||||
; Now save it back to ValueA
|
||||
SETD ValueA
|
||||
STA ; High byte
|
||||
INCD
|
||||
STB ; Low byte.
|
||||
; Now retrieve value A from the stack and store it in ValueB.
|
||||
POPB
|
||||
POPA
|
||||
SETD ValueB
|
||||
STA
|
||||
INCD
|
||||
STB
|
||||
; Print ValueA.
|
||||
SETD ValueA
|
||||
LDA
|
||||
CALL printByteHex
|
||||
INCD
|
||||
LDA
|
||||
CALL printByteHex
|
||||
CALL blankSpace
|
||||
; Now add ValueA and ValueB, and store the result in ValueA.
|
||||
; Add the low bytes of ValueA and ValueB
|
||||
SETD ValueB
|
||||
INCD
|
||||
LDA
|
||||
SETD ValueA
|
||||
INCD
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
; Store the result in ValueA.
|
||||
STQ
|
||||
; Now add the high bytes of ValueA and ValueB.
|
||||
DECD
|
||||
LDB
|
||||
SETD ValueB
|
||||
LDA
|
||||
ADD
|
||||
; If this addition overflows, we're done.
|
||||
BRC end
|
||||
; Otherwise, store the result in ValueA.
|
||||
SETD ValueA
|
||||
STQ
|
||||
; And branch back to the beginning of the loop.
|
||||
BRI start
|
||||
end:
|
||||
CALL lineFeed
|
||||
HALT
|
||||
|
||||
#Data
|
||||
|
||||
ValueA:
|
||||
; Low byte, high byte.
|
||||
0x00 0x01
|
||||
|
||||
ValueB:
|
||||
; Low byte, high byte.
|
||||
0x00 0x00
|
||||
@@ -0,0 +1,132 @@
|
||||
; A Fibonacci number generating program that uses four bytes to store the value.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
start:
|
||||
; Swap ValueB and ValueA.
|
||||
; First, store ValueA on the stack.
|
||||
SETD ValueA
|
||||
LDA
|
||||
PSHA
|
||||
INCD
|
||||
LDA
|
||||
PSHA
|
||||
INCD
|
||||
LDA
|
||||
PSHA
|
||||
INCD
|
||||
LDA
|
||||
PSHA
|
||||
; Next, store ValueB on the stack.
|
||||
SETD ValueB
|
||||
LDA
|
||||
PSHA
|
||||
INCD
|
||||
LDA
|
||||
PSHA
|
||||
INCD
|
||||
LDA
|
||||
PSHA
|
||||
INCD
|
||||
LDA
|
||||
PSHA
|
||||
; Then pop ValueB into ValueA.
|
||||
SETD ValueA
|
||||
INCD INCD INCD
|
||||
POPA
|
||||
STA
|
||||
DECD
|
||||
POPA
|
||||
STA
|
||||
DECD
|
||||
POPA
|
||||
STA
|
||||
DECD
|
||||
POPA
|
||||
STA
|
||||
; Then pop ValueA into ValueB.
|
||||
SETD ValueB
|
||||
INCD INCD INCD
|
||||
POPA
|
||||
STA
|
||||
DECD
|
||||
POPA
|
||||
STA
|
||||
DECD
|
||||
POPA
|
||||
STA
|
||||
DECD
|
||||
POPA
|
||||
STA
|
||||
; Print ValueA.
|
||||
SETD ValueA
|
||||
INCD INCD INCD
|
||||
LDA
|
||||
CALL printByteHex
|
||||
DECD
|
||||
LDA
|
||||
CALL printByteHex
|
||||
DECD
|
||||
LDA
|
||||
CALL printByteHex
|
||||
DECD
|
||||
LDA
|
||||
CALL printByteHex
|
||||
CALL blankSpace
|
||||
; Now add ValueA and ValueB, and store the result in ValueA.
|
||||
; Add the lowest bytes of ValueA and ValueB.
|
||||
SETD ValueB
|
||||
LDB
|
||||
SETD ValueA
|
||||
LDA
|
||||
ADD
|
||||
; Store it in ValueA's lowest byte.
|
||||
STQ
|
||||
; Add the second lowest bytes of ValueA and ValueB.
|
||||
SETD ValueB
|
||||
INCD
|
||||
LDB
|
||||
SETD ValueA
|
||||
INCD
|
||||
LDA
|
||||
ADD
|
||||
; Store it in ValueA's second lowest byte.
|
||||
STQ
|
||||
; Add the second highest bytes of ValueA and ValueB.
|
||||
SETD ValueB
|
||||
INCD INCD
|
||||
LDB
|
||||
SETD ValueA
|
||||
INCD INCD
|
||||
LDA
|
||||
ADD
|
||||
; Store it in ValueA's third lowest byte.
|
||||
STQ
|
||||
; Add the highest bytes of ValueA and ValueB.
|
||||
SETD ValueB
|
||||
INCD INCD INCD
|
||||
LDB
|
||||
SETD ValueA
|
||||
INCD INCD INCD
|
||||
LDA
|
||||
ADD
|
||||
; If this addition overflows, we're done.
|
||||
BRC end
|
||||
; Otherwise, store the result in ValueA's highest byte.
|
||||
STQ
|
||||
; And branch back to the beginning of the loop.
|
||||
BRI start
|
||||
end:
|
||||
CALL lineFeed
|
||||
HALT
|
||||
|
||||
#Data
|
||||
|
||||
ValueA:
|
||||
; Lowest byte ... Highest byte.
|
||||
0x01 0x00 0x00 0x00
|
||||
|
||||
ValueB:
|
||||
; Lowest byte ... Highest byte.
|
||||
0x00 0x00 0x00 0x00
|
||||
@@ -0,0 +1,33 @@
|
||||
; A Fibonacci number generating program that uses only one byte to store the value.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
start:
|
||||
; Load our initial values into A and B.
|
||||
INIA 0x00
|
||||
CALL printByteDecimal
|
||||
CALL blankSpace
|
||||
; Move the value into B.
|
||||
PSHA
|
||||
POPB
|
||||
; Load the next starting value into A.
|
||||
INIA 0x01
|
||||
CALL printByteDecimal
|
||||
CALL blankSpace
|
||||
loop:
|
||||
ADD ; Add the values together.
|
||||
BRC end ; If the value overflows, we're done.
|
||||
; Copy A into B
|
||||
PSHA
|
||||
POPB
|
||||
; Copy Q into A
|
||||
PSHQ
|
||||
POPA
|
||||
; Print A.
|
||||
CALL printByteDecimal
|
||||
CALL blankSpace
|
||||
BRI loop ; Loop again.
|
||||
end:
|
||||
CALL lineFeed
|
||||
HALT
|
||||
@@ -0,0 +1,326 @@
|
||||
; Conway's Game of Life for SplitBit.
|
||||
;
|
||||
; The visible field is 16x16, surrounded by a permanently dead one-cell border.
|
||||
; Each of the 18x18 allocated cells is stored as two adjacent bytes:
|
||||
; current state, next state
|
||||
; This makes double buffering possible with SplitBit's single Data Pointer.
|
||||
;
|
||||
; The initial pattern is a glider. ANSI terminal control codes redraw the field
|
||||
; in place. Press Ctrl-C to stop the emulator.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
CALL seedGlider
|
||||
SETD ClearScreen
|
||||
CALL printString
|
||||
|
||||
generationLoop:
|
||||
CALL renderBoard
|
||||
CALL evolveBoard
|
||||
CALL commitBoard
|
||||
CALL frameDelay
|
||||
BRI generationLoop
|
||||
|
||||
seedGlider:
|
||||
; Coordinates in the padded field:
|
||||
; .#.
|
||||
; ..#
|
||||
; ###
|
||||
SETD Board
|
||||
DPUP 0d42
|
||||
INIA 0x01
|
||||
STA
|
||||
SETD Board
|
||||
DPUP 0d80
|
||||
STA
|
||||
SETD Board
|
||||
DPUP 0d112
|
||||
STA
|
||||
SETD Board
|
||||
DPUP 0d114
|
||||
STA
|
||||
SETD Board
|
||||
DPUP 0d116
|
||||
STA
|
||||
RET
|
||||
|
||||
renderBoard:
|
||||
SETD CursorHome
|
||||
CALL printString
|
||||
SETD Board
|
||||
DPUP 0d38
|
||||
INIA 0d16
|
||||
SETD RowCount
|
||||
STA
|
||||
SETD Board
|
||||
DPUP 0d38
|
||||
|
||||
renderRow:
|
||||
PSHD
|
||||
INIA 0d16
|
||||
SETD ColCount
|
||||
STA
|
||||
POPD
|
||||
|
||||
renderCell:
|
||||
LDA
|
||||
BRA renderDead
|
||||
INIB 0x23
|
||||
OUTB 0x00
|
||||
BRI renderCellDone
|
||||
renderDead:
|
||||
INIB 0x20
|
||||
OUTB 0x00
|
||||
renderCellDone:
|
||||
DPUP 0d02
|
||||
PSHD
|
||||
SETD ColCount
|
||||
LDA
|
||||
DECA
|
||||
STA
|
||||
BRA renderRowDone
|
||||
POPD
|
||||
BRI renderCell
|
||||
|
||||
renderRowDone:
|
||||
POPD
|
||||
CALL lineFeed
|
||||
DPUP 0d04
|
||||
PSHD
|
||||
SETD RowCount
|
||||
LDA
|
||||
DECA
|
||||
STA
|
||||
BRA renderDone
|
||||
POPD
|
||||
BRI renderRow
|
||||
|
||||
renderDone:
|
||||
POPD
|
||||
RET
|
||||
|
||||
evolveBoard:
|
||||
SETD Board
|
||||
DPUP 0d38
|
||||
INIA 0d16
|
||||
SETD RowCount
|
||||
STA
|
||||
SETD Board
|
||||
DPUP 0d38
|
||||
|
||||
evolveRow:
|
||||
PSHD
|
||||
INIA 0d16
|
||||
SETD ColCount
|
||||
STA
|
||||
POPD
|
||||
|
||||
evolveCellLoop:
|
||||
CALL evolveCell
|
||||
DPUP 0d02
|
||||
PSHD
|
||||
SETD ColCount
|
||||
LDA
|
||||
DECA
|
||||
STA
|
||||
BRA evolveRowDone
|
||||
POPD
|
||||
BRI evolveCellLoop
|
||||
|
||||
evolveRowDone:
|
||||
POPD
|
||||
DPUP 0d04
|
||||
PSHD
|
||||
SETD RowCount
|
||||
LDA
|
||||
DECA
|
||||
STA
|
||||
BRA evolveDone
|
||||
POPD
|
||||
BRI evolveRow
|
||||
|
||||
evolveDone:
|
||||
POPD
|
||||
RET
|
||||
|
||||
; DP points to the current-state byte of a visible cell.
|
||||
evolveCell:
|
||||
CALL countNeighbors
|
||||
PSHQ
|
||||
LDA
|
||||
POPB
|
||||
|
||||
; Three neighbors always produces a live cell.
|
||||
INIA 0d03
|
||||
CCF
|
||||
SUB
|
||||
BRQ makeAlive
|
||||
|
||||
; Two neighbors preserve the current state.
|
||||
INIA 0d02
|
||||
CCF
|
||||
SUB
|
||||
BRQ preserveCell
|
||||
|
||||
makeDead:
|
||||
RSTA
|
||||
INCD
|
||||
STA
|
||||
DECD
|
||||
RET
|
||||
|
||||
preserveCell:
|
||||
LDA
|
||||
BRA makeDead
|
||||
|
||||
makeAlive:
|
||||
INIA 0x01
|
||||
INCD
|
||||
STA
|
||||
DECD
|
||||
RET
|
||||
|
||||
; Return the sum of the eight neighboring current-state bytes in Q.
|
||||
; With interleaved cells and an 18-cell row, the relative offsets are:
|
||||
; -38, -36, -34, -2, +2, +34, +36, +38.
|
||||
countNeighbors:
|
||||
RSTA
|
||||
DPDN 0d38
|
||||
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPA
|
||||
DPUP 0d02
|
||||
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPA
|
||||
DPUP 0d02
|
||||
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPA
|
||||
DPUP 0d32
|
||||
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPA
|
||||
DPUP 0d04
|
||||
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPA
|
||||
DPUP 0d32
|
||||
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPA
|
||||
DPUP 0d02
|
||||
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPA
|
||||
DPUP 0d02
|
||||
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
; Copy every next-state byte to its adjacent current-state byte.
|
||||
; The border's next bytes remain zero, so it stays permanently dead.
|
||||
commitBoard:
|
||||
SETD Board
|
||||
INIA 0d18
|
||||
SETD RowCount
|
||||
STA
|
||||
SETD Board
|
||||
|
||||
commitRow:
|
||||
PSHD
|
||||
INIA 0d18
|
||||
SETD ColCount
|
||||
STA
|
||||
POPD
|
||||
|
||||
commitCell:
|
||||
INCD
|
||||
LDA
|
||||
DECD
|
||||
STA
|
||||
DPUP 0d02
|
||||
PSHD
|
||||
SETD ColCount
|
||||
LDA
|
||||
DECA
|
||||
STA
|
||||
BRA commitRowDone
|
||||
POPD
|
||||
BRI commitCell
|
||||
|
||||
commitRowDone:
|
||||
POPD
|
||||
PSHD
|
||||
SETD RowCount
|
||||
LDA
|
||||
DECA
|
||||
STA
|
||||
BRA commitDone
|
||||
POPD
|
||||
BRI commitRow
|
||||
|
||||
commitDone:
|
||||
POPD
|
||||
RET
|
||||
|
||||
; Approximately 0.2 seconds at the emulator's nominal 1 MHz rate.
|
||||
frameDelay:
|
||||
INIA 0xFF
|
||||
delayOuter:
|
||||
INIB 0xFF
|
||||
delayInner:
|
||||
DECB
|
||||
BRB delayInnerDone
|
||||
BRI delayInner
|
||||
delayInnerDone:
|
||||
DECA
|
||||
BRA delayDone
|
||||
BRI delayOuter
|
||||
delayDone:
|
||||
RET
|
||||
|
||||
#Data
|
||||
|
||||
RowCount:
|
||||
0x00
|
||||
ColCount:
|
||||
0x00
|
||||
|
||||
ClearScreen:
|
||||
0x1B
|
||||
"[2J"
|
||||
CursorHome:
|
||||
0x1B
|
||||
"[H"
|
||||
|
||||
; The emulator zero-fills the remainder of Data Memory. Board names the first
|
||||
; byte of a 648-byte logical allocation (18 * 18 * 2).
|
||||
Board:
|
||||
0x00
|
||||
@@ -0,0 +1,266 @@
|
||||
; Conway's Game of Life rewritten for SplitBit's four-Data-Pointer ISA.
|
||||
;
|
||||
; The representation and display match 16x16Life.asm: a visible 16x16 field,
|
||||
; a dead border, and interleaved current/next bytes. DP0 walks the board, DP1
|
||||
; and DP2 address the loop counters, and volatile DP3 walks the neighborhood.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
CALL seedGlider
|
||||
SETD.0 ClearScreen
|
||||
CALL printString
|
||||
|
||||
generationLoop:
|
||||
CALL renderBoard
|
||||
CALL evolveBoard
|
||||
CALL commitBoard
|
||||
CALL frameDelay
|
||||
BRI generationLoop
|
||||
|
||||
seedGlider:
|
||||
SETD.0 Board
|
||||
DPUP.0 0d42
|
||||
INIA 0x01
|
||||
STA.0
|
||||
SETD.0 Board
|
||||
DPUP.0 0d80
|
||||
STA.0
|
||||
SETD.0 Board
|
||||
DPUP.0 0d112
|
||||
STA.0
|
||||
DPUP.0 0d02
|
||||
STA.0
|
||||
DPUP.0 0d02
|
||||
STA.0
|
||||
RET
|
||||
|
||||
renderBoard:
|
||||
SETD.0 CursorHome
|
||||
CALL printString
|
||||
SETD.1 RowCount
|
||||
SETD.2 ColCount
|
||||
INIA 0d16
|
||||
STA.1
|
||||
SETD.0 Board
|
||||
DPUP.0 0d38
|
||||
|
||||
renderRow:
|
||||
INIA 0d16
|
||||
STA.2
|
||||
renderCell:
|
||||
LDA.0
|
||||
BRA renderDead
|
||||
INIB 0x23
|
||||
OUTB 0x00
|
||||
BRI renderCellDone
|
||||
renderDead:
|
||||
INIB 0x20
|
||||
OUTB 0x00
|
||||
renderCellDone:
|
||||
DPUP.0 0d02
|
||||
LDA.2
|
||||
DECA
|
||||
STA.2
|
||||
BRA renderRowDone
|
||||
BRI renderCell
|
||||
|
||||
renderRowDone:
|
||||
CALL lineFeed
|
||||
DPUP.0 0d04
|
||||
LDA.1
|
||||
DECA
|
||||
STA.1
|
||||
BRA renderDone
|
||||
BRI renderRow
|
||||
renderDone:
|
||||
RET
|
||||
|
||||
evolveBoard:
|
||||
SETD.1 RowCount
|
||||
SETD.2 ColCount
|
||||
INIA 0d16
|
||||
STA.1
|
||||
SETD.0 Board
|
||||
DPUP.0 0d38
|
||||
|
||||
evolveRow:
|
||||
INIA 0d16
|
||||
STA.2
|
||||
evolveCellLoop:
|
||||
CALL evolveCell
|
||||
DPUP.0 0d02
|
||||
LDA.2
|
||||
DECA
|
||||
STA.2
|
||||
BRA evolveRowDone
|
||||
BRI evolveCellLoop
|
||||
|
||||
evolveRowDone:
|
||||
DPUP.0 0d04
|
||||
LDA.1
|
||||
DECA
|
||||
STA.1
|
||||
BRA evolveDone
|
||||
BRI evolveRow
|
||||
evolveDone:
|
||||
RET
|
||||
|
||||
evolveCell:
|
||||
CALL countNeighbors
|
||||
MVQB ; B is the neighbor count from here down.
|
||||
|
||||
; Three neighbors always produces a live cell.
|
||||
INIA 0d03
|
||||
CCF
|
||||
SUB
|
||||
BRQ makeAlive
|
||||
|
||||
; Two neighbors preserve the current state.
|
||||
INIA 0d02
|
||||
CCF
|
||||
SUB
|
||||
BRQ preserveCell
|
||||
|
||||
makeDead:
|
||||
RSTA
|
||||
INCD.0
|
||||
STA.0
|
||||
DECD.0
|
||||
RET
|
||||
|
||||
preserveCell:
|
||||
LDA.0
|
||||
BRA makeDead
|
||||
|
||||
makeAlive:
|
||||
INIA 0x01
|
||||
INCD.0
|
||||
STA.0
|
||||
DECD.0
|
||||
RET
|
||||
|
||||
; Return the eight-neighbor sum in Q. One Stack round-trip copies DP0 into
|
||||
; volatile DP3; MVQA then keeps the running total entirely in registers.
|
||||
countNeighbors:
|
||||
PSHD.0
|
||||
POPD.3
|
||||
RSTA
|
||||
DPDN.3 0d38
|
||||
|
||||
LDB.3
|
||||
CCF
|
||||
ADD
|
||||
MVQA
|
||||
DPUP.3 0d02
|
||||
|
||||
LDB.3
|
||||
CCF
|
||||
ADD
|
||||
MVQA
|
||||
DPUP.3 0d02
|
||||
|
||||
LDB.3
|
||||
CCF
|
||||
ADD
|
||||
MVQA
|
||||
DPUP.3 0d32
|
||||
|
||||
LDB.3
|
||||
CCF
|
||||
ADD
|
||||
MVQA
|
||||
DPUP.3 0d04
|
||||
|
||||
LDB.3
|
||||
CCF
|
||||
ADD
|
||||
MVQA
|
||||
DPUP.3 0d32
|
||||
|
||||
LDB.3
|
||||
CCF
|
||||
ADD
|
||||
MVQA
|
||||
DPUP.3 0d02
|
||||
|
||||
LDB.3
|
||||
CCF
|
||||
ADD
|
||||
MVQA
|
||||
DPUP.3 0d02
|
||||
|
||||
LDB.3
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
commitBoard:
|
||||
SETD.1 RowCount
|
||||
SETD.2 ColCount
|
||||
INIA 0d18
|
||||
STA.1
|
||||
SETD.0 Board
|
||||
|
||||
commitRow:
|
||||
INIA 0d18
|
||||
STA.2
|
||||
commitCell:
|
||||
INCD.0
|
||||
LDA.0
|
||||
DECD.0
|
||||
STA.0
|
||||
DPUP.0 0d02
|
||||
LDA.2
|
||||
DECA
|
||||
STA.2
|
||||
BRA commitRowDone
|
||||
BRI commitCell
|
||||
|
||||
commitRowDone:
|
||||
LDA.1
|
||||
DECA
|
||||
STA.1
|
||||
BRA commitDone
|
||||
BRI commitRow
|
||||
commitDone:
|
||||
RET
|
||||
|
||||
frameDelay:
|
||||
INIA 0xFF
|
||||
delayOuter:
|
||||
INIB 0xFF
|
||||
delayInner:
|
||||
DECB
|
||||
BRB delayInnerDone
|
||||
BRI delayInner
|
||||
delayInnerDone:
|
||||
DECA
|
||||
BRA delayDone
|
||||
BRI delayOuter
|
||||
delayDone:
|
||||
RET
|
||||
|
||||
#Data
|
||||
|
||||
RowCount:
|
||||
0x00
|
||||
ColCount:
|
||||
0x00
|
||||
|
||||
ClearScreen:
|
||||
0x1B
|
||||
"[2J"
|
||||
CursorHome:
|
||||
0x1B
|
||||
"[H"
|
||||
|
||||
; 18 by 18 cells with the current and next states interleaved, so 648 bytes. The
|
||||
; original leaves this implicit and leans on Data Memory being zero, which works but
|
||||
; means the assembler believes the board is one byte long: anything placed after it
|
||||
; would land inside it, and nothing would say so. Reserving the region states how far
|
||||
; it reaches, so a label added below here is safe.
|
||||
Board:
|
||||
#Reserve 0d648
|
||||
@@ -0,0 +1,20 @@
|
||||
; This is a basic hello world program for the SplitBit CPU.
|
||||
; We'll create a loop that outputs each byte of our string to Output 0, the text console.
|
||||
|
||||
#Program
|
||||
|
||||
Start:
|
||||
LDA ; Load a byte of the string into A.
|
||||
BRA End ; If A is zero, branch out of the loop.
|
||||
OUTA 0x00 ; Output the value in A to Port 0, the text console.
|
||||
INCD ; Increment the Data Pointer to the next byte of the string.
|
||||
BRI Start ; Branch immediately to the start of the loop.
|
||||
|
||||
End:
|
||||
INIA 0x0A ; We'll load a linefeed into A and output it to make it look nice.
|
||||
OUTA 0x00 ; Output it to the text console.
|
||||
HALT ; Terminate the program.
|
||||
|
||||
#Data
|
||||
|
||||
"Hello, World!"
|
||||
@@ -0,0 +1,55 @@
|
||||
; This program asks the user for input, then prints whatever they input back to the console again.
|
||||
; It stores the input string in a buffer in the Data Memory.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
SETD Message0 ; Set the Data Pointer to the explanation message.
|
||||
CALL printString ; Print it out.
|
||||
CALL lineFeed
|
||||
SETD Buffer ; Set the Data Pointer to the start of the buffer.
|
||||
INIB 0x0A ; Load the value of a linefeed into B.
|
||||
inputLoop:
|
||||
INA 0x00 ; Poll the command line.
|
||||
CCF
|
||||
SUB
|
||||
BRQ inputEnd ; If we encountered a linefeed, the string is over, proceed to processing.
|
||||
STA ; Store A into the buffer.
|
||||
INCD ; Increment to the next spot in the buffer.
|
||||
BRI inputLoop ; Loop again to grab more string.
|
||||
inputEnd:
|
||||
INIA 0x00 ; Set A to 0.
|
||||
STA ; Store it in the buffer.
|
||||
SETD Buffer ; Set the Data Pointer to the start of the buffer again.
|
||||
CALL printString ; Print it out.
|
||||
CALL lineFeed
|
||||
HALT ; End the program.
|
||||
|
||||
#Data
|
||||
|
||||
; A 256 character buffer for the input string.
|
||||
; There will need to be some kind of way to define large arrays better than this...
|
||||
Buffer:
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
|
||||
Message0:
|
||||
"Input Test: Will echo anything you put in."
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
; A segmented Sieve of Eratosthenes for the complete 16-bit address range.
|
||||
;
|
||||
; The sieve uses a 256-byte sliding window. Each entry in PrimeStates contains:
|
||||
; prime, high byte of next multiple, low byte of next multiple
|
||||
;
|
||||
; Once a prime becomes active at p*p, adding an 8-bit prime to offsets in a
|
||||
; 256-byte window must wrap exactly once before the next window. The wrapped
|
||||
; low byte becomes that prime's starting offset in the following window.
|
||||
;
|
||||
; Output is hexadecimal (0002 through FFFD), separated by spaces.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
RSTA
|
||||
SETD Page
|
||||
STA
|
||||
|
||||
nextPage:
|
||||
; Clear all 256 flags. A wrapping to zero terminates the loop.
|
||||
SETD Segment
|
||||
RSTA
|
||||
RSTB
|
||||
clearSegment:
|
||||
STB
|
||||
INCD
|
||||
INCA
|
||||
BRA segmentCleared
|
||||
BRI clearSegment
|
||||
|
||||
segmentCleared:
|
||||
; Zero and one are not prime.
|
||||
SETD Page
|
||||
LDA
|
||||
BRA excludeZeroAndOne
|
||||
BRI markSegment
|
||||
excludeZeroAndOne:
|
||||
SETD Segment
|
||||
INIA 0x01
|
||||
STA
|
||||
INCD
|
||||
STA
|
||||
|
||||
markSegment:
|
||||
; Process the 54 primes not greater than sqrt(0xFFFF).
|
||||
SETD PrimeStates
|
||||
INIA 0d54
|
||||
primeLoop:
|
||||
CALL processPrime
|
||||
DPUP 0d03
|
||||
DECA
|
||||
BRA scanSegment
|
||||
BRI primeLoop
|
||||
|
||||
scanSegment:
|
||||
; A is the low byte of the candidate and wraps after 0xFF.
|
||||
SETD Segment
|
||||
RSTA
|
||||
scanLoop:
|
||||
LDB
|
||||
BRB emitPrime
|
||||
scanNext:
|
||||
INCD
|
||||
INCA
|
||||
BRA advancePage
|
||||
BRI scanLoop
|
||||
|
||||
emitPrime:
|
||||
CALL printCandidateHex
|
||||
BRI scanNext
|
||||
|
||||
advancePage:
|
||||
SETD Page
|
||||
LDA
|
||||
INCA
|
||||
STA
|
||||
BRA finished
|
||||
BRI nextPage
|
||||
|
||||
finished:
|
||||
CALL lineFeed
|
||||
HALT
|
||||
|
||||
; DP points at a PrimeStates entry on entry and is preserved by CALL.
|
||||
processPrime:
|
||||
PSHD
|
||||
INCD
|
||||
LDA
|
||||
SETD Page
|
||||
LDB
|
||||
XOR
|
||||
BRQ primeIsActive
|
||||
POPD
|
||||
RET
|
||||
|
||||
primeIsActive:
|
||||
; Recover and retain the state-entry pointer for the final update.
|
||||
POPD
|
||||
PSHD
|
||||
|
||||
; Load the prime into B and its current offset into A.
|
||||
LDA
|
||||
PSHA
|
||||
DPUP 0d02
|
||||
LDA
|
||||
POPB
|
||||
|
||||
; Form Segment + offset. Segment is page-aligned in Data Memory.
|
||||
SETD Segment
|
||||
PSHB
|
||||
PSHD
|
||||
POPB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPD
|
||||
POPB
|
||||
|
||||
markPrimeLoop:
|
||||
INIA 0x01
|
||||
STA
|
||||
|
||||
; Add the prime to the low byte of DP using the stack as a 16-bit
|
||||
; address adapter. Carry means that the next multiple is in the next page.
|
||||
PSHD
|
||||
POPA
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPD
|
||||
BRC primeFinished
|
||||
BRI markPrimeLoop
|
||||
|
||||
primeFinished:
|
||||
; Q is the wrapped offset for the next page.
|
||||
POPD
|
||||
INCD
|
||||
LDA
|
||||
INCA
|
||||
STA
|
||||
INCD
|
||||
STQ
|
||||
RET
|
||||
|
||||
; A contains the candidate's low byte. Page contains its high byte.
|
||||
printCandidateHex:
|
||||
PSHA
|
||||
SETD Page
|
||||
LDA
|
||||
CALL printByteHex
|
||||
POPA
|
||||
CALL printByteHex
|
||||
CALL blankSpace
|
||||
RET
|
||||
|
||||
#Data
|
||||
|
||||
; This has to begin on a page boundary, and now says so itself rather than relying on
|
||||
; whatever happens to have been assembled before it. The marking loop treats a carry out
|
||||
; of the low byte as the end of the page, which only finds the right boundary if the
|
||||
; window starts on one.
|
||||
|
||||
#Align 0x100
|
||||
Segment:
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
|
||||
Page:
|
||||
0x00
|
||||
|
||||
PrimeStates:
|
||||
0x02 0x00 0x04
|
||||
0x03 0x00 0x09
|
||||
0x05 0x00 0x19
|
||||
0x07 0x00 0x31
|
||||
0x0B 0x00 0x79
|
||||
0x0D 0x00 0xA9
|
||||
0x11 0x01 0x21
|
||||
0x13 0x01 0x69
|
||||
0x17 0x02 0x11
|
||||
0x1D 0x03 0x49
|
||||
0x1F 0x03 0xC1
|
||||
0x25 0x05 0x59
|
||||
0x29 0x06 0x91
|
||||
0x2B 0x07 0x39
|
||||
0x2F 0x08 0xA1
|
||||
0x35 0x0A 0xF9
|
||||
0x3B 0x0D 0x99
|
||||
0x3D 0x0E 0x89
|
||||
0x43 0x11 0x89
|
||||
0x47 0x13 0xB1
|
||||
0x49 0x14 0xD1
|
||||
0x4F 0x18 0x61
|
||||
0x53 0x1A 0xE9
|
||||
0x59 0x1E 0xF1
|
||||
0x61 0x24 0xC1
|
||||
0x65 0x27 0xD9
|
||||
0x67 0x29 0x71
|
||||
0x6B 0x2C 0xB9
|
||||
0x6D 0x2E 0x69
|
||||
0x71 0x31 0xE1
|
||||
0x7F 0x3F 0x01
|
||||
0x83 0x43 0x09
|
||||
0x89 0x49 0x51
|
||||
0x8B 0x4B 0x79
|
||||
0x95 0x56 0xB9
|
||||
0x97 0x59 0x11
|
||||
0x9D 0x60 0x49
|
||||
0xA3 0x67 0xC9
|
||||
0xA7 0x6C 0xF1
|
||||
0xAD 0x74 0xE9
|
||||
0xB3 0x7D 0x29
|
||||
0xB5 0x7F 0xF9
|
||||
0xBF 0x8E 0x81
|
||||
0xC1 0x91 0x81
|
||||
0xC5 0x97 0x99
|
||||
0xC7 0x9A 0xB1
|
||||
0xD3 0xAD 0xE9
|
||||
0xDF 0xC2 0x41
|
||||
0xE3 0xC9 0x49
|
||||
0xE5 0xCC 0xD9
|
||||
0xE9 0xD4 0x11
|
||||
0xEF 0xDF 0x21
|
||||
0xF1 0xE2 0xE1
|
||||
0xFB 0xF6 0x19
|
||||
@@ -0,0 +1,224 @@
|
||||
; The 16-bit segmented sieve rewritten for SplitBit's four-Data-Pointer ISA.
|
||||
;
|
||||
; This deliberately implements the same algorithm and emits the same text as
|
||||
; 16bitSegmentedSieve.asm, making the two versions useful as a direct comparison.
|
||||
; DP0 walks PrimeStates, DP1 holds Page, DP2 walks Segment, and volatile DP3
|
||||
; marks multiples. CALL preserves the first three pointers automatically.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
RSTA
|
||||
SETD.1 Page
|
||||
STA.1
|
||||
|
||||
nextPage:
|
||||
SETD.2 Segment
|
||||
RSTA
|
||||
RSTB
|
||||
clearSegment:
|
||||
STB.2
|
||||
INCD.2
|
||||
INCA
|
||||
BRA segmentCleared
|
||||
BRI clearSegment
|
||||
|
||||
segmentCleared:
|
||||
; Zero and one are not prime.
|
||||
LDA.1
|
||||
BRA excludeZeroAndOne
|
||||
BRI markSegment
|
||||
excludeZeroAndOne:
|
||||
SETD.2 Segment
|
||||
INIA 0x01
|
||||
STA.2
|
||||
INCD.2
|
||||
STA.2
|
||||
|
||||
markSegment:
|
||||
SETD.0 PrimeStates
|
||||
INIA 0d54
|
||||
primeLoop:
|
||||
CALL processPrime
|
||||
DPUP.0 0d03
|
||||
DECA
|
||||
BRA scanSegment
|
||||
BRI primeLoop
|
||||
|
||||
scanSegment:
|
||||
SETD.2 Segment
|
||||
RSTA
|
||||
scanLoop:
|
||||
LDB.2
|
||||
BRB emitPrime
|
||||
scanNext:
|
||||
INCD.2
|
||||
INCA
|
||||
BRA advancePage
|
||||
BRI scanLoop
|
||||
|
||||
emitPrime:
|
||||
CALL printCandidateHex
|
||||
BRI scanNext
|
||||
|
||||
advancePage:
|
||||
LDA.1
|
||||
INCA
|
||||
STA.1
|
||||
BRA finished
|
||||
BRI nextPage
|
||||
|
||||
finished:
|
||||
CALL lineFeed
|
||||
HALT
|
||||
|
||||
; DP0 points at a PrimeStates entry. CALL restores it on return.
|
||||
processPrime:
|
||||
INCD.0
|
||||
LDA.0
|
||||
LDB.1
|
||||
XOR
|
||||
BRQ primeIsActive
|
||||
RET
|
||||
|
||||
primeIsActive:
|
||||
; B is the prime and A its current offset.
|
||||
DECD.0
|
||||
LDB.0
|
||||
DPUP.0 0d02
|
||||
LDA.0
|
||||
|
||||
; DP3 = Segment + offset. Only this one initial pointer copy needs the Stack.
|
||||
SETD.3 Segment
|
||||
PSHB
|
||||
PSHD.3
|
||||
POPB
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPD.3
|
||||
POPB
|
||||
|
||||
markPrimeLoop:
|
||||
INIA 0x01
|
||||
STA.3
|
||||
|
||||
; Add the prime to DP3's low byte. A carry crosses into the next window.
|
||||
PSHD.3
|
||||
POPA
|
||||
CCF
|
||||
ADD
|
||||
PSHQ
|
||||
POPD.3
|
||||
BRC primeFinished
|
||||
BRI markPrimeLoop
|
||||
|
||||
primeFinished:
|
||||
; DP0 is on the offset byte; advance the saved high byte and save Q as
|
||||
; the wrapped offset for the following page.
|
||||
DECD.0
|
||||
LDA.0
|
||||
INCA
|
||||
STA.0
|
||||
INCD.0
|
||||
STQ.0
|
||||
RET
|
||||
|
||||
printCandidateHex:
|
||||
PSHA
|
||||
LDA.1
|
||||
CALL printByteHex
|
||||
POPA
|
||||
CALL printByteHex
|
||||
CALL blankSpace
|
||||
RET
|
||||
|
||||
#Data
|
||||
|
||||
; Segment has to begin on a page boundary, and now says so itself rather than relying on
|
||||
; whatever happens to have been assembled before it. The marking loop adds the prime to
|
||||
; the low byte of DP3 and treats the carry out as the end of the page, so it only finds
|
||||
; the right boundary if the window starts on one.
|
||||
;
|
||||
; The whole window is written out here so that Page and PrimeStates begin after it.
|
||||
|
||||
#Align 0x100
|
||||
Segment:
|
||||
0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
|
||||
Page:
|
||||
0x00
|
||||
|
||||
PrimeStates:
|
||||
0x02 0x00 0x04
|
||||
0x03 0x00 0x09
|
||||
0x05 0x00 0x19
|
||||
0x07 0x00 0x31
|
||||
0x0B 0x00 0x79
|
||||
0x0D 0x00 0xA9
|
||||
0x11 0x01 0x21
|
||||
0x13 0x01 0x69
|
||||
0x17 0x02 0x11
|
||||
0x1D 0x03 0x49
|
||||
0x1F 0x03 0xC1
|
||||
0x25 0x05 0x59
|
||||
0x29 0x06 0x91
|
||||
0x2B 0x07 0x39
|
||||
0x2F 0x08 0xA1
|
||||
0x35 0x0A 0xF9
|
||||
0x3B 0x0D 0x99
|
||||
0x3D 0x0E 0x89
|
||||
0x43 0x11 0x89
|
||||
0x47 0x13 0xB1
|
||||
0x49 0x14 0xD1
|
||||
0x4F 0x18 0x61
|
||||
0x53 0x1A 0xE9
|
||||
0x59 0x1E 0xF1
|
||||
0x61 0x24 0xC1
|
||||
0x65 0x27 0xD9
|
||||
0x67 0x29 0x71
|
||||
0x6B 0x2C 0xB9
|
||||
0x6D 0x2E 0x69
|
||||
0x71 0x31 0xE1
|
||||
0x7F 0x3F 0x01
|
||||
0x83 0x43 0x09
|
||||
0x89 0x49 0x51
|
||||
0x8B 0x4B 0x79
|
||||
0x95 0x56 0xB9
|
||||
0x97 0x59 0x11
|
||||
0x9D 0x60 0x49
|
||||
0xA3 0x67 0xC9
|
||||
0xA7 0x6C 0xF1
|
||||
0xAD 0x74 0xE9
|
||||
0xB3 0x7D 0x29
|
||||
0xB5 0x7F 0xF9
|
||||
0xBF 0x8E 0x81
|
||||
0xC1 0x91 0x81
|
||||
0xC5 0x97 0x99
|
||||
0xC7 0x9A 0xB1
|
||||
0xD3 0xAD 0xE9
|
||||
0xDF 0xC2 0x41
|
||||
0xE3 0xC9 0x49
|
||||
0xE5 0xCC 0xD9
|
||||
0xE9 0xD4 0x11
|
||||
0xEF 0xDF 0x21
|
||||
0xF1 0xE2 0xE1
|
||||
0xFB 0xF6 0x19
|
||||
@@ -0,0 +1,67 @@
|
||||
; This is an implementation of The Sieve of Eratosthenes that finds all the primes between 2 and 255.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
; Search the list until we find a prime.
|
||||
SETD DataTop
|
||||
CCF ; Clear the carry flag. In later cycles, the carry flag will be set at the end of the next loop. We'll want it cleared.
|
||||
RSTA
|
||||
RSTB
|
||||
findPrimeLoop:
|
||||
LDB ; Load an element into B.
|
||||
BRB foundPrime ; If it's zero, it's a prime.
|
||||
INCA ; Increment A, our index.
|
||||
INCD ; Increment the Data Pointer.
|
||||
BRA end ; If A becomes zero, we've looked through the whole list without finding another prime.
|
||||
BRI findPrimeLoop ; Keep searching for the next prime.
|
||||
foundPrime:
|
||||
; If we've found a prime, we should print it and mark it off the list so we don't print it again.
|
||||
CALL printByteDecimal ; A contains our prime, so we can just call the print subroutine.
|
||||
CALL blankSpace ; Put a space afterward to keep things easy to read.
|
||||
INIB 0x01 ; Set B to 1.
|
||||
STB ; Mark this prime off the list.
|
||||
markMultiples:
|
||||
; Now, we mark each multiple of this prime as nonprime until we reach the end of the list.
|
||||
PSHD ; Save the Data Pointer to the stack.
|
||||
POPB ; Pop its low byte into B.
|
||||
ADD ; Add them together.
|
||||
PSHQ ; Store the result back onto the stack.
|
||||
POPD ; Pop the modified address into the Data Pointer.
|
||||
INIB 0x01 ; Set B to 1.
|
||||
STB ; Store B to mark the value as nonprime.
|
||||
BRC start ; If the previous add overflowed, the next nonprime is outside the range of our list, so start over with a new prime.
|
||||
BRI markMultiples ; Otherwise, loop again to mark the next multiple as nonprime.
|
||||
end:
|
||||
CALL lineFeed ; Print a linefeed to make it look nice.
|
||||
HALT ; The program is done, we found all the primes!
|
||||
|
||||
|
||||
|
||||
|
||||
#Data
|
||||
|
||||
; The table of our prime candidates. It has to begin on a page boundary: marking walks
|
||||
; the pointer's low byte and treats the carry out as running off the end of the table,
|
||||
; which only finds the right end if the table starts on one.
|
||||
|
||||
#Align 0x100
|
||||
DataTop:
|
||||
0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
@@ -0,0 +1,32 @@
|
||||
; printHello.asm
|
||||
|
||||
; As a demonstration of the new print routines, here's a new implementation for hello.asm
|
||||
; Anachronaut
|
||||
; 10/27/2024
|
||||
|
||||
; Include the subroutine file.
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
SETD MyString ; Set the Data Pointer to the start of MyString.
|
||||
CALL printString ; Call the string printing subroutine.
|
||||
CALL lineFeed ; Call the line feed subroutine to end the line.
|
||||
SETD MyDecimal ; Set the Data Pointer to the value to print as a decimal.
|
||||
LDA ; Load it into A.
|
||||
CALL printByteDecimal ; Call the decimal printing subroutine.
|
||||
SETD MyMessage ; Set the Data Pointer to another string.
|
||||
CALL printString ; Call the string printing subroutine again.
|
||||
CALL lineFeed ; Call the line feed subroutine to end the line.
|
||||
HALT ; Stop the program.
|
||||
#Data
|
||||
|
||||
MyString:
|
||||
"Hello, World! "
|
||||
|
||||
MyDecimal:
|
||||
0d42
|
||||
|
||||
MyMessage:
|
||||
" is the great answer."
|
||||
@@ -0,0 +1,410 @@
|
||||
; Interactive hexadecimal calculator for SplitBit.
|
||||
;
|
||||
; Enter expressions as:
|
||||
; HH operator HH
|
||||
; Whitespace is optional. Supported operators are + - * & | and ^.
|
||||
; Arithmetic wraps to eight bits. Enter Q to quit.
|
||||
|
||||
#Include print.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
SETD Welcome
|
||||
CALL printString
|
||||
|
||||
repl:
|
||||
SETD Prompt
|
||||
CALL printString
|
||||
|
||||
CALL readNonSpace
|
||||
PSHQ
|
||||
POPA
|
||||
|
||||
; Q, q, or end-of-file exits.
|
||||
INIB 0xFF
|
||||
XOR
|
||||
BRQ quit
|
||||
INIB 0x51
|
||||
XOR
|
||||
BRQ quit
|
||||
INIB 0x71
|
||||
XOR
|
||||
BRQ quit
|
||||
|
||||
CALL readHexByteFirst
|
||||
SETD LeftOperand
|
||||
STQ
|
||||
CALL parseIsInvalid
|
||||
BRQ inputError
|
||||
|
||||
CALL readNonSpace
|
||||
PSHQ
|
||||
POPA
|
||||
SETD Operator
|
||||
STA
|
||||
|
||||
CALL readNonSpace
|
||||
PSHQ
|
||||
POPA
|
||||
CALL readHexByteFirst
|
||||
SETD RightOperand
|
||||
STQ
|
||||
CALL parseIsInvalid
|
||||
BRQ inputError
|
||||
|
||||
CALL discardLine
|
||||
CALL evaluate
|
||||
SETD Result
|
||||
STQ
|
||||
CALL operatorIsInvalid
|
||||
BRQ operatorError
|
||||
|
||||
SETD Result
|
||||
LDA
|
||||
CALL printByteHex
|
||||
CALL lineFeed
|
||||
BRI repl
|
||||
|
||||
inputError:
|
||||
CALL discardLine
|
||||
SETD BadInput
|
||||
CALL printString
|
||||
BRI repl
|
||||
|
||||
operatorError:
|
||||
SETD BadOperator
|
||||
CALL printString
|
||||
BRI repl
|
||||
|
||||
quit:
|
||||
SETD Goodbye
|
||||
CALL printString
|
||||
HALT
|
||||
|
||||
; Read a character other than space, tab, CR, or LF. Return it in Q.
|
||||
readNonSpace:
|
||||
readNonSpaceLoop:
|
||||
INA 0x00
|
||||
INIB 0x20
|
||||
XOR
|
||||
BRQ readNonSpaceLoop
|
||||
INIB 0x09
|
||||
XOR
|
||||
BRQ readNonSpaceLoop
|
||||
INIB 0x0A
|
||||
XOR
|
||||
BRQ readNonSpaceLoop
|
||||
INIB 0x0D
|
||||
XOR
|
||||
BRQ readNonSpaceLoop
|
||||
INIB 0x00
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
; A contains the first hexadecimal digit. Read the second and return the byte
|
||||
; in Q. Q is 0xFF on malformed input.
|
||||
readHexByteFirst:
|
||||
CALL clearParseStatus
|
||||
CALL hexNibble
|
||||
PSHQ
|
||||
POPA
|
||||
INIB 0xFF
|
||||
XOR
|
||||
BRQ invalidByte
|
||||
INIB 0x00
|
||||
SHL
|
||||
SHL
|
||||
SHL
|
||||
SHL
|
||||
PSHA
|
||||
|
||||
CALL readNonSpace
|
||||
PSHQ
|
||||
POPA
|
||||
CALL hexNibble
|
||||
PSHQ
|
||||
POPA
|
||||
INIB 0xFF
|
||||
XOR
|
||||
BRQ invalidLowNibble
|
||||
POPB
|
||||
OR
|
||||
RET
|
||||
|
||||
invalidLowNibble:
|
||||
POPB
|
||||
invalidByte:
|
||||
PSHD
|
||||
SETD ParseStatus
|
||||
INIA 0x01
|
||||
STA
|
||||
POPD
|
||||
INIA 0xFF
|
||||
INIB 0x00
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
; Convert the ASCII hexadecimal digit in A to a value in Q.
|
||||
; Uppercase and lowercase letters are accepted. Q=0xFF means invalid.
|
||||
hexNibble:
|
||||
PSHA
|
||||
|
||||
; Try 0 through 9.
|
||||
INIB 0x30
|
||||
CCF
|
||||
SUB
|
||||
BRC tryUpperHex
|
||||
PSHQ
|
||||
POPA
|
||||
INIB 0d10
|
||||
CCF
|
||||
SUB
|
||||
BRC decimalNibble
|
||||
|
||||
tryUpperHex:
|
||||
POPA
|
||||
PSHA
|
||||
INIB 0x41
|
||||
CCF
|
||||
SUB
|
||||
BRC tryLowerHex
|
||||
PSHQ
|
||||
POPA
|
||||
INIB 0d06
|
||||
CCF
|
||||
SUB
|
||||
BRC upperNibble
|
||||
|
||||
tryLowerHex:
|
||||
POPA
|
||||
PSHA
|
||||
INIB 0x61
|
||||
CCF
|
||||
SUB
|
||||
BRC badNibble
|
||||
PSHQ
|
||||
POPA
|
||||
INIB 0d06
|
||||
CCF
|
||||
SUB
|
||||
BRC lowerNibble
|
||||
|
||||
badNibble:
|
||||
POPA
|
||||
INIA 0xFF
|
||||
INIB 0x00
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
decimalNibble:
|
||||
POPB
|
||||
INIB 0x00
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
upperNibble:
|
||||
POPB
|
||||
INIB 0d10
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
lowerNibble:
|
||||
POPB
|
||||
INIB 0d10
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
; Return Q=0 if Q was 0xFF, otherwise return a nonzero value.
|
||||
resultIsInvalid:
|
||||
PSHQ
|
||||
POPA
|
||||
INIB 0xFF
|
||||
XOR
|
||||
RET
|
||||
|
||||
clearParseStatus:
|
||||
PSHD
|
||||
SETD ParseStatus
|
||||
RSTA
|
||||
STA
|
||||
POPD
|
||||
RET
|
||||
|
||||
parseIsInvalid:
|
||||
PSHD
|
||||
SETD ParseStatus
|
||||
LDA
|
||||
INIB 0x01
|
||||
XOR
|
||||
POPD
|
||||
RET
|
||||
|
||||
operatorIsInvalid:
|
||||
PSHD
|
||||
SETD OperatorStatus
|
||||
LDA
|
||||
INIB 0x01
|
||||
XOR
|
||||
POPD
|
||||
RET
|
||||
|
||||
; Evaluate the stored expression and return its result in Q.
|
||||
evaluate:
|
||||
PSHD
|
||||
SETD OperatorStatus
|
||||
RSTA
|
||||
STA
|
||||
POPD
|
||||
SETD Operator
|
||||
LDA
|
||||
|
||||
INIB 0x2B
|
||||
XOR
|
||||
BRQ evaluateAdd
|
||||
INIB 0x2D
|
||||
XOR
|
||||
BRQ evaluateSubtract
|
||||
INIB 0x2A
|
||||
XOR
|
||||
BRQ evaluateMultiply
|
||||
INIB 0x26
|
||||
XOR
|
||||
BRQ evaluateAnd
|
||||
INIB 0x7C
|
||||
XOR
|
||||
BRQ evaluateOr
|
||||
INIB 0x5E
|
||||
XOR
|
||||
BRQ evaluateXor
|
||||
|
||||
SETD OperatorStatus
|
||||
INIA 0x01
|
||||
STA
|
||||
RSTA
|
||||
INIB 0x00
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
evaluateAdd:
|
||||
SETD LeftOperand
|
||||
LDA
|
||||
INCD
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
evaluateSubtract:
|
||||
SETD LeftOperand
|
||||
LDA
|
||||
INCD
|
||||
LDB
|
||||
CCF
|
||||
SUB
|
||||
RET
|
||||
|
||||
evaluateAnd:
|
||||
SETD LeftOperand
|
||||
LDA
|
||||
INCD
|
||||
LDB
|
||||
AND
|
||||
RET
|
||||
|
||||
evaluateOr:
|
||||
SETD LeftOperand
|
||||
LDA
|
||||
INCD
|
||||
LDB
|
||||
OR
|
||||
RET
|
||||
|
||||
evaluateXor:
|
||||
SETD LeftOperand
|
||||
LDA
|
||||
INCD
|
||||
LDB
|
||||
XOR
|
||||
RET
|
||||
|
||||
evaluateMultiply:
|
||||
RSTA
|
||||
SETD Product
|
||||
STA
|
||||
|
||||
multiplyLoop:
|
||||
SETD RightOperand
|
||||
LDA
|
||||
BRA multiplyDone
|
||||
DECA
|
||||
STA
|
||||
|
||||
SETD Product
|
||||
LDA
|
||||
SETD LeftOperand
|
||||
LDB
|
||||
CCF
|
||||
ADD
|
||||
SETD Product
|
||||
STQ
|
||||
BRI multiplyLoop
|
||||
|
||||
multiplyDone:
|
||||
SETD Product
|
||||
LDA
|
||||
INIB 0x00
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
; Consume the rest of the current input line.
|
||||
discardLine:
|
||||
discardLoop:
|
||||
INA 0x00
|
||||
INIB 0x0A
|
||||
XOR
|
||||
BRQ discardDone
|
||||
INIB 0xFF
|
||||
XOR
|
||||
BRQ discardDone
|
||||
BRI discardLoop
|
||||
discardDone:
|
||||
RET
|
||||
|
||||
#Data
|
||||
|
||||
LeftOperand:
|
||||
0x00
|
||||
RightOperand:
|
||||
0x00
|
||||
Operator:
|
||||
0x00
|
||||
Product:
|
||||
0x00
|
||||
Result:
|
||||
0x00
|
||||
ParseStatus:
|
||||
0x00
|
||||
OperatorStatus:
|
||||
0x00
|
||||
|
||||
Welcome:
|
||||
"SplitBit calculator (+ - * & | ^), Q quits."
|
||||
Prompt:
|
||||
0x0A
|
||||
"> "
|
||||
BadInput:
|
||||
"Invalid hexadecimal input."
|
||||
BadOperator:
|
||||
"Unknown operator."
|
||||
Goodbye:
|
||||
"Goodbye!"
|
||||
0x0A
|
||||
Reference in New Issue
Block a user