Metropoli BBS
VIEWER: bcd.asm MODE: TEXT (ASCII)
%TITLE  "Binary-Coded-Decimal (BCD) routines"

	IDEAL
	DOSSEG
	MODEL	small

;------ Equates
ASCIINull	EQU 	0
PackedSize	EQU	10
UnpackedSize	EQU	20


	UDATASEG

TempUPBCD	dt	?, ?

	CODESEG

	PUBLIC	BCDAdd, BCDSubtract, PackedToUnpacked
	PUBLIC	UnpackedToPacked, BCDToASCII, BCDCopy

%NEWPAGE
;------------------------------------------------------------------------
; BCDAdd - adds two packed BCD numbers
;------------------------------------------------------------------------
;	Input:   si = address of source BCD value (10 bytes)
;                di = address of destination BCD value (10 bytes)
;	Output:  destinationBCD <- destinationBCD + sourceBCD
;		 cf = 0 : NO error
;		 cf = 1 : OVERFLOW error occurred
;       Registers:  none
;------------------------------------------------------------------------
PROC	BCDAdd
	push	ax
	push	cx
	push	di
	push	si
	cld
	clc
	mov	cx, PackedSize
@@10:
	lodsb
	adc	al,[byte di]
	daa
	stosb
	loop	@@10
	pop	si
	pop	di
	pop	cx
	pop	ax
	ret
ENDP	BCDAdd

%NEWPAGE
;------------------------------------------------------------------------
; BCDSubtract - subtracts two packed BCD numbers
;------------------------------------------------------------------------
;	Input:   si = address of source BCD value (10 bytes)
;                di = address of destination BCD value (10 bytes)
;	Output:  destinationBCD <- destinationBCD - sourceBCD
;		 cf = 0 : NO error
;		 cf = 1 : UNDERFLOW error occurred
;       Registers:  none
;------------------------------------------------------------------------
PROC	BCDSubtract
	push	ax
	push	cx
	push	di
	push	si
	cld
	clc
	mov	cx, PackedSize
@@10:
	lodsb
	sbb	[byte di],al
	mov	al,[byte di]
	das
	stosb
	loop	@@10
	pop	si
	pop	di
	pop	cx
	pop	ax
	ret
ENDP	BCDSubtract

%NEWPAGE
;------------------------------------------------------------------------
; PackedToUnpacked - convert packed BCD to Unpacked BCD
;------------------------------------------------------------------------
;	Input:   si = address of source packed BCD value (10 bytes)
;                di = address of destination unpacked BCD value (20 bytes)
;	Output:  destinationBCD <- unpacked(sourceBCD)
;       Registers:  none
;------------------------------------------------------------------------
PROC	PackedToUnpacked
	push	ax
	push	cx
	push	di
	push	si
	cld
	mov	cx,PackedSize
@@10:
	lodsb
	mov	ah,al
	shr	ah,1
	shr	ah,1
	shr	ah,1
	shr	ah,1
	and	al,0Fh
	stosw
	loop	@@10
	pop	si
	pop	di
	pop	cx
	pop	ax
	ret
ENDP	PackedToUnpacked

%NEWPAGE
;------------------------------------------------------------------------
; UnpackedToPacked - convert Unpacked BCD to packed BCD
;------------------------------------------------------------------------
;	Input:   si = address of source unpacked BCD value (20 bytes)
;                di = address of destination packed BCD value (10 bytes)
;	Output:  destinationBCD <- packed(sourceBCD)
;       Registers:  none
;------------------------------------------------------------------------
PROC	UnpackedToPacked
	push	ax
	push	cx
	push	di
	push	si
	cld
	mov	cx,PackedSize
@@10:
	lodsw
	shr	ah,1
	shr	ah,1
	shr	ah,1
	shr	ah,1
	or	al,ah
	stosb
	loop	@@10
	pop	si
	pop	di
	pop	cx
	pop	ax
	ret
ENDP	UnpackedToPacked

%NEWPAGE
;------------------------------------------------------------------------
; BCDToASCII - convert packed BCD value to ASCII
;------------------------------------------------------------------------
;	Input:   si = address of source packed BCD value (10 bytes)
;                di = address of destination ASCIIZ string (21 bytes)
;	Output:  ASCIIZ <- ASCII(sourceBCD) + null character
;       Registers:  none
;------------------------------------------------------------------------
PROC	BCDToASCII
	push	ax
	push	cx
	push	di
	push	si
	push	di
	mov	di, offset TempUPBCD
	call	PackedToUnpacked
	pop	di
	mov	si,offset TempUPBCD + UnpackedSize - 2
	mov	cx,PackedSize
@@10:
	std
	lodsw
	or	ax,03030h
	xchg	ah,al
	cld
	stosw
	loop	@@10
	mov	[byte,di],ASCIINull
	pop	si
	pop	di
	pop	cx
	pop	ax
	ret
ENDP	BCDToASCII

%NEWPAGE
;------------------------------------------------------------------------
; BCDCopy - copy a packed BCD value
;------------------------------------------------------------------------
;	Input:   si = address of source BCD value (10 bytes)
;                di = address of destination BCD value (10 bytes)
;	Output:  destinationBCD <- sourceBCD
;       Registers:  none
;------------------------------------------------------------------------
PROC	BCDCopy
	push	cx
	push	di
	push	si
	cld
	mov	cx,PackedSize/2
	rep	movsw
	pop	si
	pop	di
	pop	cx
	ret
ENDP	BCDCopy

	END

[ RETURN TO DIRECTORY ]