The memory map gave CosmOS 0x0000 through 0x1FFF of Program Memory and applications 0x2000 and above. CosmOS is 8141 bytes at the previous commit, which is fifty one bytes short of the line, and the next thing added to it went over. GOING OVER DOES NOT FAIL WHERE IT HAPPENS. Nothing enforces the division: an application says where it goes with #Base and the loader puts it there, so a CosmOS that has grown past 0x1FFF simply has the next program loaded written over the end of it. What breaks is whichever part of the shell that program happened to cover, at whatever later moment somebody uses it. It turned up here as the monitor's assemble command answering "I do not know" to valid instructions, several commands into a session, on a machine that had booted perfectly well. Both halves are doubled: applications now start at 0x4000 in Program Memory and 0x2000 in Data Memory. That is 16K of code and 8K of data for the system, against the 8775 and 2948 it uses today. Both were on the same trajectory, and moving them together means the twenty files that say #Base are edited once rather than twice. The standalone loader's loadable.asm keeps its old base: it belongs to the loader CosmOS grew out of, not to CosmOS, and its addresses answer to a different program. The unbased-segment diagnostic keeps its old base too - it exists to produce an error message that names the address, and the message is what is recorded. Tests/docs.sh now reads the two limits out of the table in the README and measures both segments against them. It reads them rather than being told them because the table is the specification, and this is the second time in this project that the thing nobody checked is the thing that rotted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
231 lines
4.7 KiB
NASM
231 lines
4.7 KiB
NASM
; 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 services.asm
|
|
|
|
#Program
|
|
|
|
#Base 0x4000
|
|
|
|
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
|
|
SWI osExit ; Return to CosmOS.
|
|
|
|
; 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
|
|
|
|
#Base 0x2000
|
|
|
|
; 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
|
|
|
|
#Include print.asm
|