title XMODEM CRC Algorithm 8086 / Lattice C Compiler
include mc.ash
.model small
;*									*
;*	clrcrc();							*
;*	CLRCRC - A call to this entry resets the CRC accumulator.	*
;*		 It must be called at the start of each message.	*
;*									*
;*		 Entry Parameters: None.				*
;*									*
;*		 Exit Conditions:  CRC accumulator cleared.		*
;*									*
;*	udcrc(c);							*
;*	char c;								*
;*	UPDCRC - A call to this entry updates the CRC accumulator.	*
;*		 It must be called once for each byte in the		*
;*		 message for which the CRC is being calculated.		*
;*									*
;*		 Entry Parameters:       a byte to be included		*
;*					 in the CRC calculation.	*
;*									*
;*		 Exit Conditions:  CRC accumulator updated.		*
;*									*
;*									*
;*	crc= fincrc();							*
;*	unsigned crc;							*
;*	FINCRC - A call to this entry finishes the CRC calculation	*
;*		 for a message which is to be TRANSMITTED. It must	*
;*		 be called after the last byte of the message has	*
;*		 been passed thru UPDCRC. It returns the calculated	*
;*		 CRC bytes, which must be transmitted as the final	*
;*		 two bytes of the message.				*
;*									*
;*		Note that this returns a single 16 bit value; 		*
;*		if transmitting bytes, it must be transmitted 		*
;*		upper half first then lower half:			*
;*									*
;*			output (crc >> 8);				*
;*			output (crc);					*
;*									*
;*									*
;*		 Entry Parameters: None.				*
;*									*
;*		 Exit Conditions:  calculated CRC bytes.		*
;*									*
;*	error= chkcrc();						*
;*	int error;							*
;*	CHKCRC - A call to this routine checks the CRC bytes of		*
;*		 a RECEIVED message and returns a code to indicate	*
;*		 whether the message was received correctly. It must	*
;*		 be called after the message AND the two CRC bytes	*
;*		 have been received AND passed thru UPDCRC.		*
;*									*
;*		 Entry Parameters: None.				*
;*									*
;*		 Exit Conditions:  0 if message ok.			*
;*				   non-zero if message garbled.		*
;*									*
page
;
;Our very own little bit of data space.
;
.data
crc	dw (?)		;calculated CRC,

.code
;
;Initialize the CRC.
;
func _clrcrc
	mov	crc,0
endf _clrcrc
;
;Update the CRC with the new byte. The method used is 
;the CCITT polynomial:
;
;	x^16 + x^12 + x^5 + 1
;
;An alternate method often used in synchronous
;protocols is:
;
;	x^16 + x^15 + x^2 + 1
;
;Which can be generated by changing the XOR pattern
;from 1021 hex to 8005 hex.
;
func _updcrc
	mov	bx,crc		;BX == CRC a reg for speed,
	mov	cx,8		;CX == bits in a byte,
	mov	ax,arg0		;AL == msg byte,

u1:	rcl	al,1		;MSB -> carry,
	rcl	bx,1		;    -> CRC LSB,
	jnc	u2
	xor	bx,1021h
u2:	loop	u1

	mov	crc,bx
endf _updcrc
;
;Finish off the CRC.
;
func _fincrc
	xor	ax,ax		;do two zeros
	push	ax
	call	_updcrc
	call	_updcrc
	pop	ax
	mov	ax,crc		;return finished CRC
endf _fincrc
;
;Check the calculated CRC. Return 0 if OK.
;
func _chkcrc
	mov	ax,crc
endf _chkcrc

	end
