dos_compilers/Borland Turbo Assembler v32/SIEVE.ASM

238 lines
6.3 KiB
NASM
Raw Normal View History

2024-07-06 15:29:33 +02:00
; 8086 assembly to compute e to n digits.
; build with masm 5.0 like this:
; ntvdm -h masm /Zi /Zd /z /l %1,,,;
; ntvdm -h link %1,,%1,,nul.def
; replicate this:
; #define TRUE 1
; #define FALSE 0
; #define SIZE 8190
;
; char flags[SIZE+1];
;
; int main()
; {
; int i,k;
; int prime,count,iter;
;
; for (iter = 1; iter <= 10; iter++) { /* do program 10 times */
; count = 0; /* initialize prime counter */
; for (i = 0; i <= SIZE; i++) /* set all flags true */
; flags[i] = TRUE;
; for (i = 0; i <= SIZE; i++) {
; if (flags[i]) { /* found a prime */
; prime = i + i + 3; /* twice index + 3 */
; for (k = i + prime; k <= SIZE; k += prime)
; flags[k] = FALSE; /* kill all multiples */
; count++; /* primes found */
; }
; }
; }
; printf("%d primes.\n",count); /*primes found in 10th pass */
; return 0;
; }
;
dosseg
.model small
.stack 100h
; DOS constants
dos_write_char equ 2h
dos_realtime_clock equ 1ah
dos_exit equ 4ch
; app constants
true equ 1
false equ 0
loops equ 10
arraysize equ 8190
dataseg segment para public 'data'
assume ds: dataseg
crlfmsg db 13,10,0
primesmsg db ' primes.',13,10,0
count dw 0
ITER dw 0
PKFLAGS dd 0
align 16
flags db arraysize + 1 dup( ? )
afterflags db 0
dataseg ends
.code
start:
mov ax, dataseg
mov ds, ax
mov cx, 0 ; handy place for 0
mov di, offset afterFlags ; handy place for this constant
iteragain: ; for ( iter = 1; iter <= 10; iter++ )
mov word ptr [ count ], 0 ; count = 0
; set all array entries to true: for (i = 0; i <= SIZE; i++) flags[i] = TRUE;
xor bx, bx
nexttrue:
mov byte ptr [ offset flags + bx ], true
inc bx
cmp bx, arraysize
jle nexttrue
; iterate through array entries and count primes
xor bx, bx ; bx is "i" in the outer for loop
nextprime: ; for (i = 0; i <= SIZE; i++) {
cmp byte ptr [ flags + bx ], 0
jz flagisoff
mov ax, 3 ; ax == prime = i + i + 3
add ax, bx
add ax, bx
mov si, offset flags
add si, bx ; for (k = i + prime; k <= SIZE; k += prime)
kloop:
add si, ax ; k += prime
cmp si, di ; is si >= offset afterFlags?
jge inccount
mov byte ptr [ si ], cl ; flags[ k ] = false. use cl for 0 because it's faster than an immediate
jmp kloop
inccount:
inc word ptr [ COUNT ] ; count++
flagisoff: ; check if outer loop is done
inc bx
cmp bx, arraysize + 1
jnz nextprime
checknextiter: ; are we done iterating loops times?
inc word ptr [ ITER ]
cmp word ptr [ ITER ], loops
jnz iteragain
mov ax, word ptr [COUNT]
call printint
call printcrlf
mov dx, offset primesmsg
call printstring
mov al, 0
mov ah, dos_exit
int 21h
;start endp
; print the integer in ax
printint proc near
test ah, 80h
push ax
push bx
push cx
push dx
push di
push si
jz _prpositive
neg ax ; just one instruction for complement + 1
push ax
mov dx, '-'
mov ah, dos_write_char
int 21h
pop ax
_prpositive:
xor cx, cx
xor dx, dx
cmp ax, 0
je _przero
_prlabel1:
cmp ax, 0
je _prprint1
mov bx, 10
div bx
push dx
inc cx
xor dx, dx
jmp _prlabel1
_prprint1:
cmp cx, 0
je _prexit
pop dx
add dx, 48
mov ah, dos_write_char
int 21h
dec cx
jmp _prprint1
_przero:
mov dx, '0'
mov ah, dos_write_char
int 21h
_prexit:
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
printint endp
printcrlf proc near
push ax
push bx
push cx
push dx
push di
push si
mov dx, offset crlfmsg
call printstring
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
printcrlf endp
printstring proc near
push ax
push bx
push cx
push dx
push di
push si
mov di, dx
_psnext:
mov al, byte ptr [ di ]
cmp al, 0
je _psdone
mov dx, ax
mov ah, dos_write_char
int 21h
inc di
jmp _psnext
_psdone:
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
printstring endp
end