RosettaCodeData/Task/Remove-duplicate-elements/8080-Assembly/remove-duplicate-elements.8080

57 lines
2.0 KiB
Plaintext

org 100h
jmp test
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Given an array of bytes starting at HL with length BC,
;; remove all duplicates in the array. The new end of the array
;; is returned in HL. A page of memory (256 bytes) is required
;; to mark which bytes have been seen.
uniqpage: equ 3 ; Page to use - a compile-time constant.
; This would need to be set to a page that
; the rest of the program doesn't need.
uniq: xra a ; Zero out the page
lxi d,uniqpage * 256
uniqzero: stax d ; Zero out a byte
inr e ; And do the next byte
jnz uniqzero
mov d,h ; Keep a second pointer to the array in DE
mov e,l
uniqpos: ldax d ; Read from high pointer
mov m,a ; Write to low pointer
inx d ; Increment the high pointer
push h ; Keep low pointer around
mvi h,uniqpage
mov l,a ; Have we seen this byte yet?
cmp m
mov m,a ; No matter what, we've certainly seen it now
pop h ; Bring back the low pointer
jz uniqno ; If we already had it, don't increment low ptr
inx h ; IF we didn't, do increment it
uniqno: dcx b ; One fewer byte left
mov a,b ; If there are zero bytes left,
ora c
rz ; Then return to caller
jmp uniqpos ; Otherwise, do the next byte
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Testing code: read a string from the CP/M console, run
;; uniq, then print the output.
test: lxi d,bufdef ; Read a string
mvi c,10
call 5
lxi d,nl ; Output on new line
mvi c,9
call 5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lda bufdef+1 ; Length of input string
mov c,a ; Extend to 16-bit (since uniq supports
mvi b,0 ; long arrays)
lxi h,buf ; Location of input string
call uniq ; Only the unique bytes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mvi m,'$' ; Mark the (string) end with '$'
lxi d,buf ; Print the string, which now has had
mvi c,9 ; all duplicates removed.
jmp 5
nl: db 13,10,'$'
bufdef: db 127,0
buf: