RosettaCodeData/Task/Van-Eck-sequence/8080-Assembly/van-eck-sequence.8080

111 lines
1.9 KiB
Plaintext

org 100h
lxi h,ecks ; Zero out 2000 bytes
lxi b,0
lxi d,2000
zero: mov m,b
inx h
dcx d
mov a,d
ora e
jnz zero
lxi b,-1 ; BC = Outer loop variable
outer: inx b
mvi a,3 ; Are we there yet? 1000 = 03E8h
cmp b ; Compare high byte
jnz go
mvi a,0E8h ; Compare low byte
cmp c
jz done
go: mov d,b ; DE = Inner loop variable
mov e,c
inner: dcx d
mov a,d ; <= 0?
ral
jc outer
push b ; Keep both pointers
push d
mov h,b ; Load BC = eck[BC]
mov l,c
call eck
mov c,m
inx h
mov b,m
xchg ; Load HL = -eck[DE]
call eck
xchg
ldax d
cma
mov l,a
inx d
ldax d
cma
mov h,a
inx h ; Two's complement
dad b ; -eck[DE] + eck[BC]
mov a,h ; Unfortunately this does not set flags
ora l ; Check zero
pop d ; Meanwhile, restore the pointers
pop b
jnz inner ; If no match, continue with inner loop
mov h,b ; If we _did_, then get &eck[BC + 1]
mov l,c
inx h
call eck
mov a,c ; Store BC - DE at that address
sub e
mov m,a
inx h
mov a,b
sbb d
mov m,a
jmp outer ; And continue the outer loop
done: lxi h,0 ; Print first 10 terms
call p10
lxi h,990 ; Print last 10 terms
p10: mvi b,10 ; Print 10 terms starting at term HL
call eck
ploop: mov e,m ; Load term into DE
inx h
mov d,m
inx h
push b ; Keep counter
push h ; Keep pointer
xchg ; Term in HL
call printn ; Print term
pop h ; Restore pointer and counter
pop b
dcr b
jnz ploop
lxi d,nl ; Print a newline afterwards
jmp prints
eck: push b ; Set HL = &eck[HL]
lxi b,ecks ; Base address
dad h ; Multiply by two
dad b ; Add base
pop b
ret
printn: lxi d,buf ; Print the number in HL
push d ; Buffer pointer on stack
lxi b,-10 ; Divisor
pdigit: lxi d,-1 ; Quotient
pdiv: inx d
dad b
jc pdiv
mvi a,'0'+10
add l ; Make ASCII digit
pop h
dcx h ; Store digit
mov m,a
push h
xchg
mov a,h ; Quotient nonzero?
ora l
jnz pdigit ; Then there are more digits
pop d ; Otherwise, print string using CP/M
prints: mvi c,9
jmp 5
nl: db 13,10,'$'
db '.....'
buf: db ' $'
ecks: equ $