237 lines
4.8 KiB
NASM
237 lines
4.8 KiB
NASM
; 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 Libraries/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
|
|
|
|
; print.asm deliberately pads its data to one page, so this begins at 0x0100.
|
|
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
|