-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprimes.s
746 lines (619 loc) · 13.6 KB
/
primes.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
// Prime number finder. First version will seive the primes up to 100.
// A basic loader. Generates:
// 10 SYS (2064)
// Notes:
//
// curr: stores the current prime we're working with
// curr_index: curr / 20
// curr_mask_index: curr % 20
//
// index_adder = amount to add to the index when we go to the next number
// mask_adder = amount to add to mask_index when we got to the next number
//
// bit_index = The physical address of the bits. (bits_index - bits = curr_index)
.pc = $0801 "Basic upstart"
:BasicUpstart(start)
// A few vars
.var bits = $0c00
.var end_bits = bits + $C350 // 50000 bytes
.var curr = $19 // some random place in the zero page that seems safe
.var curr_index = $1e
.var curr_mask_index = $21
.var screen_enable = $02
.var bit_mask_index = $41
.var bit_index = $43
.var index_adder_1 = $57
.var index_adder_2 = $58
.var index_adder_3 = $59
.var index_adder_4 = $5a
.var mask_adder_1 = $5f
.var mask_adder_2 = $60
.var mask_adder_3 = $61
.var mask_adder_4 = $62
.var BIT7 = $fb
.var BIT3 = $fc
.var calculating_location = $07b0
.var display_msg_work = $e0
.var display_msg_ptr = $e3
.var index_and_mask_to_hex_work_index = $e4
.var index_and_mask_to_hex_work_hex = $e7
.var index_and_mask_to_hex_work_mask = $eb
.var hex_lo = $ec
.var hex_hi = $ed
.var bit_mask = $87
.pc = $0810 // 2064, Enough room over the BasicStart
start:
// Prep some vars
lda #$80
sta BIT7
lda #$08
sta BIT3
// Turn off the basic rom
lda #$36
sta $01
// Back up the zero page, so I can reload basic afterwards
// This is going into the IO area, but all writes go to RAM, no
// matter how things area configured
ldx #$ff
copy_zp:
lda $00,x
sta $e000,x
dex
bne copy_zp
// Black out the screen
lda #$00
sta $d021
sta $d020
// clear the screen
ldx #$00
lda #$20
clear_screen:
dex
sta $0400,X
sta $0500,X
sta $0600,X
sta $0700,X
bne clear_screen
// Display the message
ldy #$17 // Y
ldx #$0a // X
lda #[clearing_memory_msg_end - clearing_memory_msg] // length
sta display_msg_work + 2 // Length
lda #<clearing_memory_msg
sta display_msg_work
lda #>clearing_memory_msg
sta display_msg_work + 1
jsr display_msg
// Clear some memory
lda #$FF
ldx #>end_bits
outer_clear_mem:
stx clear_mem + 3 // self modding code.
ldy #$00
clear_mem:
dey
sta bits,y // Self modding code.
bne clear_mem
dex
cpx #>bits - 1
bne outer_clear_mem
// Copy 20 bytes for the bit mask.
ldx #$00
copy_table:
lda bit_mask_table, x
sta bit_mask, x
inx
cpx #$14 // compare to 20
bne copy_table
// We know that 1 is not prime, so lets turn that bit off now.
lda #$FE
sta bits
// Some initialization
lda #$03
sta bit_mask_index
sta curr_mask_index
lda #>bits
sta bit_index + 1
// Start with 3 as the first number to seive
lda #$03
sta curr
lda #$00
sta curr + 1
sta curr + 2
sta curr + 3
sta curr + 4
sta curr_index
sta curr_index + 1
sta bit_index
// Display the message
ldy #$17 // Y
ldx #$0a // X
lda #[calculating_msg_end - calculating_msg] // length
sta display_msg_work + 2 // Length
lda #<calculating_msg
sta display_msg_work
lda #>calculating_msg
sta display_msg_work + 1
tsx
txa
pha
break2:
jsr display_msg
// Turn off the screen
lda $d011
sta screen_enable
lda #$00
sta $d011
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
next_number:
// Copy the number to the accum.
lda curr_mask_index
// Now multiply curr_index and curr_mask_index by 2 to get the adders
asl // remainder
cmp #$14
bcc mask_adder_skip_carry_1
sbc #$14
mask_adder_skip_carry_1:
sta mask_adder_1
sta mask_adder_3
sta mask_adder_4
lda curr_index
rol
sta index_adder_1
sta index_adder_3
sta index_adder_4
lda mask_adder_1
asl // remainder
cmp #$14
bcc mask_adder_skip_carry_2
sbc #$14
mask_adder_skip_carry_2:
sta mask_adder_2
lda index_adder_1
rol
sta index_adder_2
// Now we have our adders. Lets start adding.
ldx #$ff // 2
txs // 2
ldy #$00
add_loop:
// Determine which adder we're using.
tsx // 2
inx // 2
txa
and #$03
tax
txs // 2
// Figure out the mask_index
// No need for clc here.
lda mask_adder_1, X
adc bit_mask_index
// Are we >= 20
cmp #$14
bcc no_mask_carry
// Yes, subtract 20 from this, and carry to the bit_index
// Note that carry flag is set here.
sbc #$14 // Let the carry flag fall through to the adc bit_index after the no_mask_carry.
// Carry flag will be set here
no_mask_carry:
sta bit_mask_index
// We don't want to clc here, since it may fall from the sbc above.
tya
adc index_adder_1, X
tay
bcc skip_carry // 3
inc bit_index+1 // 5
skip_carry:
lda bit_index+1 // 3
// Are we done? We already have the byte we want in there, no need to load
cmp #>[end_bits]
bcs r_we_done // if >=, check the lower byte
set_the_bit:
// We now have the index we need, and an offset to our bit mask. Turn that
// bit off.
ldx bit_mask_index // WHich of the masks we are using
lda bit_mask,X // Load that mask
and (bit_index),y // And it with the data pointed to by bit_index
sta (bit_index),y // Store the updated data
jmp add_loop
r_we_done:
// Check the lower byte.
cpy #<[end_bits]
bcc set_the_bit
find_next_num:
// Find the bit/mask index for the curr num. The next prime to sieve.
clc
lda #>bits
adc curr_index + 1
sta curr_index + 1
// curr_mask_index has the mask index
ldx curr_mask_index
ldy #$00
next_num_loop:
inx // 2
inx // 2
cpx #$14 // 2
bcc no_mask_carry_2 // 2, 3 on branch
// No clc needed here
txa // 2
sbc #$14 // 2
tax // 2
inc curr_index
bne no_mask_carry_2
inc curr_index + 1
no_mask_carry_2:
lda bit_mask, X
// Now check the bit in that location
ora (curr_index), Y
cmp #$FF
bne next_num_loop
// Store the data for the next loop
stx curr_mask_index
stx bit_mask_index
lda curr_index + 1
sta bit_index + 1
sec
sbc #>bits
sta curr_index + 1
// Are we done?
lda curr_index
sta bit_index
cmp #$32 // $32 is the quotient of 1000 / 20.
bcs summit
jmp next_number
break:
summit:
lda screen_enable
sta $d011
// Display the message
ldy #$17 // Y
ldx #$0a // X
lda #[summing_msg_end - summing_msg] // length
sta display_msg_work + 2 // Length
lda #<summing_msg
sta display_msg_work
lda #>summing_msg
sta display_msg_work + 1
jsr display_msg
// Sum things together.
lda #$07 // 2 and 5 are prime.
sta curr
lda #$00
sta curr + 1
sta curr + 2
sta curr + 3
sta curr + 4
lda #<bits
sta curr_index
lda #>bits
sta curr_index + 1
ldx #$01 // Start on the first bit, next it'll advance to the 3rd bit
next_num_loop_2:
ldy #$00
inx
inx
cpx #$14
bcc no_mask_carry_3
// No clc needed here
txa
sbc #$14
tax
inc curr_index
bne no_mask_carry_3
inc curr_index + 1
no_mask_carry_3:
// Are we done?
lda curr_index + 1
cmp #>[end_bits - 1]
bcc r_we_done_4 // <, if its less than, skip the second test
r_we_done_3:
lda curr_index
cmp #<[end_bits]
bcs end_prg // < Both of these mean we continue
r_we_done_4:
lda bit_mask, X
beq next_num_loop_2 // skip 0's
// Now check the bit in that location
ora (curr_index), Y
cmp #$FF
bne next_num_loop_2
stx curr_mask_index
// We now have the index and mask, convert to a hex value.
txa
sta index_and_mask_to_hex_work_mask
lda curr_index
sta index_and_mask_to_hex_work_index
lda curr_index + 1
sec
sbc #>bits
sta index_and_mask_to_hex_work_index + 1
jsr index_and_mask_to_hex
clc
lda index_and_mask_to_hex_work_hex
adc curr
sta curr
lda index_and_mask_to_hex_work_hex + 1
adc curr + 1
sta curr + 1
lda index_and_mask_to_hex_work_hex + 2
adc curr + 2
sta curr + 2
lda index_and_mask_to_hex_work_hex + 3
adc curr + 3
sta curr + 3
lda #$00
adc curr + 4
sta curr + 4
// Display something
jsr display_curr
ldx curr_mask_index
jmp next_num_loop_2
end_prg:
// copy the zp back
sei
// Let us see the io page.
lda #$34
sta $01
// Copy the data back to the zp.
ldx #$02
copy_zp_3: lda $e000,x
sta $00,x
inx
bne copy_zp_3
pla
tax
txs
// Renable the io page and basic.
//lda #$37
//sta $01
cli
rts
display_curr:
ldx #$05
ldy #$FE
display_loop:
dex
iny
iny
txa
pha
tya
pha
lda curr, x
jsr get_hex
pla
tay
pla
tax
lda hex_hi
sta calculating_location, y
lda hex_lo
sta calculating_location + 1, y
cpx #$00
bne display_loop
rts
get_hex:
// Take a byte in A, and stores the chars to display in x and Y
tay
and #$f0
lsr
lsr
lsr
lsr
tax
lda print_table,x
sta hex_hi
tya
and #$0f
tax
lda print_table,x
sta hex_lo
rts
display_ret:
.byte 0, 0
display_msg:
lda #$04
sta display_msg_ptr + 1
lda #$00
sta display_msg_ptr
add_y:
cpy #$00
beq done_y
clc
lda #40
adc display_msg_ptr
sta display_msg_ptr
lda #$00
adc display_msg_ptr + 1
sta display_msg_ptr + 1
dey
jmp add_y
done_y:
txa
clc
adc display_msg_ptr
sta display_msg_ptr
lda #$00
adc display_msg_ptr + 1
sta display_msg_ptr + 1
ldy #$00
write_to_screen:
lda (display_msg_work),Y
sta (display_msg_ptr),Y
iny
cpy display_msg_work + 2
bne write_to_screen
rts
index_and_mask_to_hex:
lda index_and_mask_to_hex_work_index
sta index_and_mask_to_hex_work_hex
lda index_and_mask_to_hex_work_index + 1
sta index_and_mask_to_hex_work_hex + 1
lda #$00
sta index_and_mask_to_hex_work_hex + 2
sta index_and_mask_to_hex_work_hex + 3
// Multiply by 16
ldx #$04
multi_loop_2:
asl index_and_mask_to_hex_work_hex
rol index_and_mask_to_hex_work_hex + 1
rol index_and_mask_to_hex_work_hex + 2
rol index_and_mask_to_hex_work_hex + 3
dex
bne multi_loop_2
// Times 4
lda #$00
sta index_and_mask_to_hex_work_index + 2
asl index_and_mask_to_hex_work_index
rol index_and_mask_to_hex_work_index + 1
rol index_and_mask_to_hex_work_index + 2
asl index_and_mask_to_hex_work_index
rol index_and_mask_to_hex_work_index + 1
rol index_and_mask_to_hex_work_index + 2
// Add in the mask index
clc
lda index_and_mask_to_hex_work_mask
adc index_and_mask_to_hex_work_index
sta index_and_mask_to_hex_work_index
lda #$00
adc index_and_mask_to_hex_work_index + 1
sta index_and_mask_to_hex_work_index + 1
lda #$00
adc index_and_mask_to_hex_work_index + 2
sta index_and_mask_to_hex_work_index + 2
// Now add'em
clc
lda index_and_mask_to_hex_work_hex
adc index_and_mask_to_hex_work_index
sta index_and_mask_to_hex_work_hex
lda index_and_mask_to_hex_work_hex + 1
adc index_and_mask_to_hex_work_index + 1
sta index_and_mask_to_hex_work_hex + 1
lda index_and_mask_to_hex_work_hex + 2
adc index_and_mask_to_hex_work_index + 2
sta index_and_mask_to_hex_work_hex + 2
lda index_and_mask_to_hex_work_hex + 3 // continue in case we carry?
adc #$00
sta index_and_mask_to_hex_work_hex + 3
rts
clearing_memory_msg:
.text "clearmem "
clearing_memory_msg_end:
calculating_msg:
.text "calulating:"
calculating_msg_end:
summing_msg:
.text "summing :"
summing_msg_end:
// I should see if I find space in the zero page for this. 20 bytes
bit_mask_table:
.byte $00, // 0
%11111110, // 1
$00, // 2
%11111101, // 3
$00, // 4
$00, // 5
$00, // 6
%11111011, // 7
$00, // 8
%11110111, // 9
$00, // 10
%11101111, // 11
$00, // 12
%11011111, // 13
$00, // 14
$00, // 15
$00, // 16
%10111111, // 17
$00, // 18
%01111111 // 19
print_table:
.byte $30,
$31,
$32,
$33,
$34,
$35,
$36,
$37,
$38,
$39,
$01,
$02,
$03,
$04,
$05,
$06,
$07