Categories
z80

Sieve of Eratosthenes z80

I’ve been trying to learn z80 assembler, and one of the programs that I typically do for that is writing a version of the Sieve of Eratosthenes. My version runs under CP/M on my CPUVILLE z80 computer.

; this program implements the sieve of eratosthenes on the z80
monitor:        equ     046fh
cpm:            equ     0fa00h
data_start:     equ     1000h
data_end:       equ     3000h
current_location:       equ     0x3000          ;word variable in RAM
line_count:             equ     0x3002          ;byte variable in RAM
byte_count:             equ     0x3003          ;byte variable in RAM
value_pointer:          equ     0x3004          ;word variable in RAM
current_value:          equ     0x3006          ;word variable in RAM
buffer:                 equ     0x3008          ;buffer in RAM -- up to stack area
var_c:  equ     0ffeh

org 0100h  ; set origin of execution
        ld de,data_start
        ld a,00h
zero_loop:
        ld (de),a
        inc de
        ld hl,data_end
        sbc hl,de
        jp nz,zero_loop

        ld de,02        ; start sieve at c=2
main_sieve_loop:        ; we are using de for this loop
        ld (var_c),de   ; store in ram too
        ld h,d          ; ld hl,de
        ld l,e          ; use hl to figure out memory location
        srl h           ; since we can store 8 bits in each memory loc
        rr l            ; we need to shift left (16 bit) 3 times
        srl h           ; https://chilliant.com/z80shift.html
        rr l            ; 2
        srl h
        rr l            ; 3
        ld a,10h
        add a,h         ; add 1000h to hl to get actual location
        ld h,a          ; here is the data in (hl)
        ld a,00000111b
        and e           ; last 3 bits of de into a - will need srl a times
        ld b,(hl)       ; load the data into b
        cp 0b           ; compare a to 0
shift_a_times_1:
        jp z,done_shift_1
        srl b
        dec a
        jp shift_a_times_1
done_shift_1:           ; a is garbage, b has the bit in the lsb position
        ld a,00000001b
        and b           ; Z flag will be correct here if zero
        ld (var_c),de   ; store de in memory
        jp nz,end_main_sieve_loop       ; non zero - just inc loop and get out
; we found a zero, now need to loop and mark composites
        ld h,d
        ld l,e          ; ld hl,de
        ld b,d
        ld c,e
start_composite_loop:   ; de stores the value in this loop
        add hl,bc       ; start at 2 * de to mark composites
        jp c,end_main_sieve_loop        ; get out if overflow 16 bit
        ld d,h
        ld e,l          ; ld de,hl
        srl h
        rr l
        srl h
        rr l
        srl h
        rr l
        ld a,10h
        add a,h
        ld h,a          ; here is the data in (hl)
        ld a,00000111b
        and e           ; a has which bit to set
        ld b,00000001b  ; start with lsb
        cp 0b           ; is a zero?
shift_a_times_2:
        jp z,done_shift_2
        sla b
        dec a
        jp shift_a_times_2
done_shift_2:
        ld a,(hl)       ; retreive what is in memory
        or b            ; mark the bit
        ld (hl),a       ; write back to memory
        ld h,d
        ld l,e          ; put hl back to where we were
        ld bc,(var_c)   ; put step into bc
        jp start_composite_loop
end_main_sieve_loop:
        ld de,(var_c)
        inc de
        jp nz,main_sieve_loop

        ld hl,data_start
        call memory_dump
        ld hl,2f00h
        call memory_dump

        ret