Microsoft (R) Macro Assembler Version 6.11 02/13/01 12:10:54 sieve.asm Page 1 - 1 PAGE 240,132 ; \SIEVE.XPL MAY-19-95 ; \Eratosthenes Sieve Prime Number Program ; ; code CRLF=9, INTOUT=11, TEXT=12; ; define SIZE = 8190; ; integer PRIME, COUNT, ITER, I, K; INCLUDE RUNTIME.ASM C ;RUNTIME.ASM 03-FEB-2001 C ;SYMBOLS THE COMPILIED XPL0 PROGRAM MUST KNOW ABOUT C 0000 CSEG SEGMENT DWORD PUBLIC 'CODE' ASSUME CS:CSEG 0000 PROGRM: 0000 83 C7 12 ADD DI,18 ;reserve space for variables 0003 B8 1FFF MOV AX,8191 ;reserve FLAGS array 0006 50 PUSH AX 0007 B8 0001 MOV AX,1 ;1-dimensional array 000A 50 PUSH AX ;ax = 1 = 1 byte per element 000B 0E PUSH CS 000C E8 0000 E CALL NEAR PTR MKARRAY;set up pointer to array and ; addr FLAGS(SIZE+1); ; reserve space in heap ; ; begin 000F 33 C0 XOR AX,AX ;TEXT statement, device = 0 0011 50 PUSH AX 0000 DSEG SEGMENT WORD PUBLIC 'DATA' 0000 31 30 30 30 20 69 L1 DB "1000 iterations",13,"Š" 74 65 72 61 74 69 6F 6E 73 0D 8A 0012 DSEG ENDS 0012 B8 0000 R MOV AX,OFFSET L1 ;address of string 0015 0E PUSH CS 0016 E8 0000 E CALL NEAR PTR INTR12 ;TEXT intrinsic ; TEXT(0, "1000 iterations ; "); 0019 C7 44 0C 0001 MOV WP [SI]+12,1 ;ITER 001E 8B 54 0C MOV DX,WP [SI]+12 0021 L2: ; for ITER:= 1, 1000 do \do program 1000 times ; begin 0021 33 C0 XOR AX,AX 0023 89 44 0A MOV WP [SI]+10,AX ; COUNT:= 0; \prime counter 0026 89 44 0E MOV WP [SI]+14,AX ;zero is already in AX 0029 92 XCHG DX,AX ;DX shadows 'for' loop ; control variable 002A L3: ; for I:= 0, SIZE do 002A 8B 5C 12 MOV BX,WP [SI]+18 ;FLAGS 002D 03 DA ADD BX,DX ;+ I 002F 42 INC DX 0030 81 FA 1FFE CMP DX,8190 ;SIZE (a constant) 0034 C6 07 FF MOV BYTE PTR [BX]+0,-1 ;delayed store (of 'true' 0037 7E F1 JLE L3 ; value) avoids AGI delay 0039 89 54 0E MOV WP [SI]+14,DX ;make sure I = SIZE+1 (XPL feature) ; FLAGS(I):= true; \set flags all true 003C 33 C0 XOR AX,AX 003E 89 44 0E MOV WP [SI]+14,AX ;I 0041 92 XCHG DX,AX 0042 L4: ; for I:= 0, SIZE do 0042 8B 5C 12 MOV BX,WP [SI]+18 ;FLAGS 0045 03 DA ADD BX,DX ;+ I 0047 8A 07 MOV AL,[BX] 0049 32 E4 XOR AH,AH ORG $-2 ;eliminate previous XOR 0049 84 C0 TEST AL,AL 004B 74 2E JE L6 ; if FLAGS(I) then \found a prime ; begin 004D 8B C2 MOV AX,DX ;I 004F 03 C0 ADD AX,AX ;+ I 0051 83 C0 03 ADD AX,3 ;+ 3 0054 89 44 08 MOV WP [SI]+8,AX ;PRIME ; PRIME:= I +I +3; \twice the index + 3 0057 03 C2 ADD AX,DX ;PRIME already in AX 0059 89 44 10 MOV WP [SI]+16,AX ;K ; K:= I + PRIME; \first multiple to kill 005C L7: 005C 8B 44 10 MOV AX,WP [SI]+16 ;can't assume AX=K because of L7: 005F 3D 1FFE CMP AX,8190 ;SIZE 0062 B8 FFFF MOV AX,-1 ;\ 0065 7E 01 JLE $+3 ; \ eliminated 0067 40 INC AX ; / ORG $-6 ;/ 0062 7F 10 JG L9 ; while K <= SIZE do ; begin 0064 8B 5C 12 MOV BX,WP [SI]+18 ;FLAGS 0067 03 D8 ADD BX,AX ;+ K ('false' stored later) ; FLAGS(K):= false; \zero a non-prime ;AX = K 0069 03 44 08 ADD AX,WP [SI]+8 ;K + PRIME 006C 89 44 10 MOV WP [SI]+16,AX ;K ; K:= K +PRIME; \next multiple 006F C6 07 00 MOV BYTE PTR [BX]+0,0 ;store 'false' (AGI) 0072 EB E8 JMP L7 ;end of 'while' loop 0074 L9: ; end; 0074 8B 44 0A MOV AX,WP [SI]+10 ;INC WP [SI]+10 is harder than 0077 40 INC AX ; you'd think. ('inc' operator?) 0078 89 44 0A MOV WP [SI]+10,AX ; COUNT:= COUNT +1; \primes found 007B L6: 007B 42 INC DX ;next I 007C 81 FA 1FFE CMP DX,8190 ;SIZE 0080 7E C0 JLE L4 0082 89 54 0E MOV WP [SI]+14,DX ;(feature?) ; end; 0085 FF 44 0C INC WP [SI]+12 ;next ITER 0088 8B 54 0C MOV DX,WP [SI]+12 ;DX is bombed so use memory variable 008B 81 FA 03E8 CMP DX,1000 ;DX is loaded for possible use at top 008F 7E 90 JLE L2 ; of loop ; end; 0091 33 C0 XOR AX,AX ;device 0 0093 50 PUSH AX 0094 8B 44 0A MOV AX,WP [SI]+10 ;COUNT 0097 0E PUSH CS 0098 E8 0000 E CALL NEAR PTR INTR11 ;INTOUT intrinsic 009B 33 C0 XOR AX,AX ;device 0 009D 50 PUSH AX 0011 DSEG SEGMENT WORD PUBLIC 'DATA' 0011 20 70 72 69 6D 65 L10 DB " primes",13,"Š" 73 0D 8A 009E DSEG ENDS 009E B8 0011 R MOV AX,OFFSET L10 ;address of string 00A1 0E PUSH CS 00A2 E8 0000 E CALL NEAR PTR INTR12 ;TEXT intrinsic ; INTOUT(0, COUNT); TEXT(0, " primes ; "); \primes found in 1000th pass 00A5 CB RETF ;return to NATIVEX, which normally ; end; ; returns to DOS PUBLIC PROGRM 00A6 CSEG ENDS END ;= 166 bytes (not including text strings in the data segment)