!to "test.prg", cbm !convtab pet !sl "test.labels" LOWER_LIMIT = 10102 UPPER_LIMIT = 10901 ptr1 = $9e tmp1 = $02 strout = $ab1e intout = $bdcd chrout = $ffd2 *= $0801 basic_header !word .next_line !word 2017 ; BASIC line number. ; !pet "ti$", $b2, 34, "000000", 34, ":" ; Set clock to 00:00:00. !byte $9e ; SYS token. !byte "0" + (start / 1000), "0" + ((start / 100) % 10) !byte "0" + ((start / 10) % 10), "0" + (start % 10) ; !pet ":", $99, "ti$" ; PRINT clock value. !byte 0 ; BASIC line end marker. .next_line !word 0 ;-------------------------------------- !zone start: lda #init_sieve_txt jsr strout jsr init_sieve lda #do_sieve_txt jsr strout jsr do_sieve lda #search_txt jsr strout lda #LOWER_LIMIT sta next_prime_index+1 jsr next_prime bcc + brk + sta .prime_1 stx .prime_1+1 .loop: jsr next_prime bcs .loop_exit sta .prime_2 stx .prime_2+1 sec lda .prime_2 sbc .prime_1 tax lda .prime_2+1 sbc .prime_1+1 bne + cpx #2 bne + lda .prime_1+1 ldx .prime_1 jsr intout lda #' ' jsr chrout lda .prime_2+1 ldx .prime_2 jsr intout lda #13 jsr chrout + lda .prime_2 sta .prime_1 lda .prime_2+1 sta .prime_1+1 jmp .loop .loop_exit: rts .prime_1: !word 0 .prime_2: !word 0 ;-------------------------------------- !zone init_sieve: lda #sieve sta ptr1+1 lda #1 ldy #0 ldx #>UPPER_LIMIT - sta (ptr1),y iny bne - inc ptr1+1 dex bne - ldy #UPPER_LIMIT jsr sqrt sta .loop_upper stx .loop_upper+1 lda #2 sta .number lda #0 sta .number+1 .outer_loop: lda .loop_upper cmp .number lda .loop_upper+1 sbc .number+1 bcc .outer_loop_exit clc lda #sieve adc .number+1 sta ptr1+1 ldy #0 lda (ptr1),y beq .skip_inner_loop lda .number asl sta .not_prime lda .number+1 rol sta .not_prime+1 .inner_loop: lda #UPPER_LIMIT sbc .not_prime+1 bcc .skip_inner_loop clc lda #sieve adc .not_prime+1 sta ptr1+1 tya sta (ptr1),y clc lda .not_prime adc .number sta .not_prime lda .not_prime+1 adc .number+1 sta .not_prime+1 bcc .inner_loop .skip_inner_loop inc .number bne .outer_loop inc .number+1 bne .outer_loop .outer_loop_exit: rts .number: !word 0 .loop_upper: !word 0 .not_prime: !word 0 ;-------------------------------------- !zone sqrt: sta .n stx .n+1 lda #0 sta .result sta .result+1 sta .one lda #%01000000 sta .one+1 - lda .one sec sbc .n sta tmp1 lda .one+1 sbc .n+1 bcs + ora tmp1 beq + lsr .one+1 ror .one lsr .one+1 ror .one jmp - + .loop: lda .one ora .one+1 beq .loop_exit clc lda .result adc .one sta .tmp lda .result+1 adc .one+1 sta .tmp+1 lda .n cmp .tmp lda .n+1 sbc .tmp+1 bcc .skip sec lda .n sbc .tmp sta .n lda .n+1 sbc .tmp+1 sta .n+1 lda .one asl sta .tmp lda .one+1 rol sta .tmp+1 clc lda .tmp adc .result sta .result lda .tmp+1 adc .result+1 sta .result+1 .skip: lsr .result+1 ror .result lsr .one+1 ror .one lsr .one+1 ror .one jmp .loop .loop_exit: lda .result ldx .result+1 rts .n: !word 0 .one: !word 0 .tmp: !word 0 .result: !word 0 ;-------------------------------------- !zone next_prime: lda next_prime_index cmp #UPPER_LIMIT bcs .no_next_prime clc lda #sieve+1 adc next_prime_index+1 sta ptr1+1 inc next_prime_index bne + inc next_prime_index+1 + ldy #0 lda (ptr1),y beq next_prime .prime_found: sec lda next_prime_index sbc #1 ldx next_prime_index+1 bcs + dex + clc .no_next_prime: rts ;-------------------------------------- init_sieve_txt: !pet "initialize sieve...",13,0 do_sieve_txt: !pet "do sieve...",13,0 search_txt: !pet "search twin primes...",13,0 next_prime_index: !word 0 sieve: ;!fill UPPER_LIMIT