; \SIEVE.XPL 8-APR-2005 ; \Eratosthenes Sieve Prime Number Program ; ; code RESERVE=3, CRLF=9, INTOUT=11, TEXT=12; ; define SIZE = \8190\1000; ; integer PRIME, COUNT, ITER, I, K; ; char FLAGS; ; 000000 INCL "D16RUN.ASM" ;The runtime support code gets "included" here. It contains the start-up code and things ; like the "intrinsic" subroutines and multiply and divide subroutines. It gets assembled ; and loaded with each XPL program. 0005C4 PROGRM ;beginning of compiled XPL code 0005C4 01013002 LDA (HP) ;add 10 to the heap pointer (HP) 0005C6 0305000A ADD 10 ; to reserve space for variables 0005C8 01033002 STA (HP) ;XPL's variables are stored in an area of memory called the "heap". The variables used ; here are assigned these locations: ; PRIME 3248 = HEAPLO+4 ; COUNT 3249 = HEAPLO+5 ; ITER 324A = HEAPLO+6 ; I 324B = HEAPLO+7 ; K 324C = HEAPLO+8 ; FLAGS 324D = HEAPLO+9 ; begin 0005CA 030103E9 LDA 1001 ;load the accumulator with SIZE+1 0005CC 031700AA CSR INTR3 ;call intrinsic no. 3 (= Reserve) 0005CE 0103324D STA (HEAPLO+9) ;store the address of the reserved ; FLAGS:= RESERVE(SIZE+1); ; space into the FLAGS variable 0005D0 001F CLR ;clear the accumulator (AC:= 0) 0005D1 0028 PSA ;push the 0 in AC onto the stack 000005D2 = CODE SETL $ ;save current CODE location and 00322C ORG DATA ; switch to DATA location (origin) 00322C 0031003000200069007400L1 DWM "1","0"," ","i","t","e","r","a","t","i","o","n","s",13,"Š" ;The string "10 iterations" is stored here. Note the L1 label. An entire 16-bit ; word is used to store each character. The D16 has words instead of bytes of memory. Two ; characters could have been packed into each word, but it made the compiled code that ; accesses characters too complicated and slow. 0000323B = DATA SETL $ ;save current DATA location and 0005D2 ORG CODE ; resume CODE location 0005D2 0301322C LDA L1 ;get address of the string 0005D4 03170153 CSR INTR12 ;call Text intrinsic (#12) ; TEXT(0, "10 iterations ; "); ;The Text intrinsic is a routine that outputs a string to a specified device. Here device ; number 0 indicates that output is to go to the console, but it could just as easily go ; to some other device, such as a printer or disk file. 0005D6 03010001 LDA 1 ;initialize the 'for' loop counter 0005D8 0103324A STA (HEAPLO+6) ; (ITER) with a 1 0005DA L2 ; for ITER:= 1, 10 do \do program 10 times ; begin 0005DA 001F CLR ;zero the COUNT variable 0005DB 01033249 STA (HEAPLO+5) ; COUNT:= 0; \prime counter 0005DD 0103324B STA (HEAPLO+7) ;also zero I 0005DF L3 ; for I:= 0, SIZE do 0005DF 0101324D LDA (HEAPLO+9) ;FLAGS 0005E1 0105324B ADD (HEAPLO+7) ;+I = address of array element 0005E3 003C MAY ;move AC to IY 0005E4 001E SET ;AC:= $FFFF (=true) 0005E5 09030000 STA (IY+0) ;store into array element 0005E7 0101324B LDA (HEAPLO+7) ;increment I 0005E9 001A INC 0005EA 0103324B STA (HEAPLO+7) 0005EC 030703E9 SUB 1001 ;compare I to SIZE+1 by subtraction 0005EE 031205DF JMI L3 ;loop back if I < SIZE+1 ; (jump if minus) ; FLAGS(I):= true; \set flags all true 0005F0 001F CLR ;I:= 0 0005F1 0103324B STA (HEAPLO+7) 0005F3 L4 ; for I:= 0, SIZE do 0005F3 0101324B LDA (HEAPLO+7) ;I 0005F5 0105324D ADD (HEAPLO+9) ;+FLAGS = address of array element 0005F7 003C MAY 0005F8 09010000 LDA (IY+0) ;get element 0005FA 030900FF AND 00FFh ;only use the low 8 bits (for safety) 0005FC 030F0625 JOZ L6 ;jump if not zero (if not 'true') ; if FLAGS(I) then \found a prime ; begin 0005FE 0101324B LDA (HEAPLO+7) ;I 000600 0105324B ADD (HEAPLO+7) ;+I 000602 03050003 ADD 3 ;+3 000604 01033248 STA (HEAPLO+4) ;PRIME ; PRIME:= I + I + 3; \twice the index + 3 000606 0105324B ADD (HEAPLO+7) ;+I 000608 0103324C STA (HEAPLO+8) ;K ; K:= I + PRIME; \first multiple to kill 00060A L7 00060A 030103E8 LDA 1000 ;SIZE 00060C 0107324C SUB (HEAPLO+8) ;-K 00060E 03110613 JPL $+5 ;this strange convolution is 000610 001F CLR ; fortunately not needed very 000611 030E0614 JMP $+3 ; often and gets overwritten 000613 001E SET ; here because the origin (ORG) 00060E ORG $-6 ; gets backed up 00060E 03120620 JMI L9 ;jump if SIZE-K is < 0 ; while K <= SIZE do ; begin 000610 0101324D LDA (HEAPLO+9) ;otherwise execute the 'while' 000612 0105324C ADD (HEAPLO+8) ; loop 000614 003C MAY 000615 001F CLR 000616 09030000 STA (IY+0) ; FLAGS(K):= false; \zero a non-prime 000618 0101324C LDA (HEAPLO+8) 00061A 01053248 ADD (HEAPLO+4) 00061C 0103324C STA (HEAPLO+8) ; K:= K + PRIME; \next multiple 00061E 030E060A JMP L7 ;loop back 000620 L9 ; end; 000620 01013249 LDA (HEAPLO+5) 000622 001A INC 000623 01033249 STA (HEAPLO+5) ; COUNT:= COUNT + 1; \primes found 000625 L6 000625 0101324B LDA (HEAPLO+7) ;bottom of "for I:= 0, SIZE do" 000627 001A INC ; loop 000628 0103324B STA (HEAPLO+7) ;increment I 00062A 030703E9 SUB 1001 ;compare I to SIZE+1 00062C 031205F3 JMI L4 ;loop back if it's less ; end; 00062E 0101324A LDA (HEAPLO+6) ;bottom of ITER loop 000630 001A INC 000631 0103324A STA (HEAPLO+6) 000633 0307000B SUB 11 000635 031205DA JMI L2 ; end; 000637 001F CLR ;push a 0 onto the stack 000638 0028 PSA ;for the console device 000639 01013249 LDA (HEAPLO+5) ;COUNT 00063B 0317012A CSR INTR11 ;call Integer Output intrinsic 00063D 001F CLR ;display a text string 00063E 0028 PSA 0000063F = CODE SETL $ 00323B ORG DATA 00323B 0020007000720069006D00L10 DWM " ","p","r","i","m","e","s",13,"Š" 00003244 = DATA SETL $ 00063F ORG CODE 00063F 0301323B LDA L10 000641 03170153 CSR INTR12 ; INTOUT(0, COUNT); TEXT(0, " primes ; "); \primes found in 10th pass 000643 002E RTN ;return to the runtime code ; end; 003244 ORG DATA ;begin the heap space at the 00003244 = HEAPLO EQU $ ; end of all of the other data 000000 END