The Damm algorithm is a checksum algorithm which detects all single digit errors and adjacent transposition errors.



The algorithm is named after H. Michael Damm.



Task

Verify the checksum, stored as last digit of an input.



	org	100h
	jmp	demo
	;;;	Given an 0-terminated ASCII string containing digits in [DE],
	;;;	see if it matches its check digit. Returns with zero flag set
	;;;	if the string matches.
damm:	mvi	c,0	; Interim digit in C, starts off at 0.
	ldax	d	; Get current byte from string
	inx	d 	; Advance the pointer
	ana	a	; Is the byte zero?
	jnz	$+5	; If not, go look up interim digit
	cmp	c	; But if so, see if the interim digit is also zero
	ret		; And return whether this was the case
	sui	'0'	; Subtract ASCII 0
	mov	b,a	; Keep digit to be processed in B
	mov	a,c	; Calculate C*10 (interim digit row index)
	add	a	; * 2
	add	a	; * 4
	add	c	; * 5
	add	a	; * 10
	add	b	; Add column index
	lxi	h,dammit
	add	l	; Table lookup (assuming H doesn't change, i.e. it
	mov	l,a	; doesn't cross a page boundary).
	mov	c,m	; Get new interim digit from table
	jmp	damm+2	; And check next character
	;;;	Table of interim digits
	;;;	NOTE: must not cross page boundary
dammit:	db	0,3,1,7,5,9,8,6,4,2
	db	7,0,9,2,1,5,4,8,6,3
	db	4,2,0,6,8,7,1,3,5,9
	db	1,7,5,0,9,8,3,4,2,6
	db	6,1,2,3,0,4,5,9,7,8
	db	3,6,7,4,2,0,9,5,8,1
	db	5,8,6,9,7,2,0,1,3,4
	db	8,9,4,5,3,6,2,0,1,7
	db	9,4,3,8,6,1,7,2,0,5
	db	2,5,8,1,4,3,6,7,9,0
	;;;	Demo code: see if the argument on the CP/M command line
	;;;	matches its input.
demo:	lxi	h,80h	; Zero-terminate input
	mov	e,m
	mvi	d,0
	inx	d
	dad	d
	mov	m,d
	lxi	d,82h	; Command line argument, skipping first space
	call	damm	; See if it validates
	mvi	c,9
	lxi	d,ok	; Print OK...
	jz	5	; ...if the checksum matches,
	lxi	d,no	; Print NOT OK otherwise.
	jmp	5
no:	db	'NOT '
ok:	db	'OK$'