241 lines
6.5 KiB
NASM
241 lines
6.5 KiB
NASM
; 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
|
|
|
|
sieve_dataseg segment para public 'sievedata'
|
|
assume ds: sieve_dataseg
|
|
|
|
crlfmsg db 13,10,0
|
|
primesmsg db ' primes.',13,10,0
|
|
ITER dw 0
|
|
PKFLAGS dd 0
|
|
|
|
align 16
|
|
flags db arraysize + 1 dup( ? )
|
|
afterflags db 0
|
|
sieve_dataseg ends
|
|
|
|
.code
|
|
|
|
start:
|
|
mov ax, sieve_dataseg
|
|
mov ds, ax
|
|
|
|
iteragain: ; for ( iter = 1; iter <= 10; iter++ )
|
|
xor dx, dx ; count of primes found
|
|
|
|
; set all array entries to true: for (i = 0; i <= SIZE; i++) flags[i] = TRUE;
|
|
|
|
mov ah, true
|
|
mov al, true
|
|
mov di, offset flags
|
|
mov cx, ( arraysize + 2 ) / 2 ; 4096
|
|
push ds
|
|
pop es
|
|
cld
|
|
rep stosw
|
|
|
|
; iterate through array entries and count primes
|
|
|
|
mov di, offset afterFlags ; handy place for this constant
|
|
xor cx, cx ; handy place for 0
|
|
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)
|
|
|
|
add si, ax ; k += prime
|
|
cmp si, di ; is si >= offset afterFlags? (i.e. k <= size)
|
|
jge inccount ; redundant check to the one in the loop below but it saves a jump instruction in the loop
|
|
|
|
kloop:
|
|
mov [ si ], cl ; flags[ k ] = false. use cl for 0 because it's faster than an immediate
|
|
add si, ax ; k += prime
|
|
cmp si, di ; is si >= offset afterFlags? (i.e. k <= size)
|
|
jl kloop
|
|
|
|
inccount:
|
|
inc dx ; 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, dx
|
|
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
|