Decimal Output

Usually numbers will be handled decimal. A related articles will be found here. The input of a decimal value and the conversion to binary is quite easy — see the article. The conversion of a binary number to decimal is more tricky. Find here an overview of various routines.
Description of the collection:
All routines have in common:
  1. Register HL holds the binary value
  2. Registers will not be saved
  3. The external routine APUT, storing the current digit.
    E.g.:
    APUT:
    	push	hl		; Save register
    	ld	hl,(DIGBUF)	; Load address of buffer
    	ld	(hl),a		; Store digit
    	inc	hl
    	ld	(hl),0		; Indicate end
    	ld	(DIGBUF),hl	; Save address
    	pop	hl		; Restore register
    	ret
    
    Before calling the conversion routine DIGBUF must be set properly. Of course APUT may be a routine to print the digit.
MethodLength of codel in bytes
Recursion25
Table (1)59
Table (2)48
Negative constants76
Positive constants47
Through BCD89

;
; Recursive conversion
;
Methode1:
	ld	bc,-10		; Get constants
Numb:
	ld	de,-1
.Numb:
	add	hl,bc		; Subtract 10s
	inc	de		; Count them
	jr	c,.Numb		; If some left keep going
	push	hl		; Save remainder - 10
	ex	de,hl
	ld	a,h		; Get the number of 10s found
	or	l		; Check for quotient non zero
	call	nz,Numb		; If non zero, recurse
	pop	hl		; Get the remainder - 10
	ld	a,l
	add	a,'0'+10	; Make the number printable
	call	APUT		; Put anywhere
	ret

;
; Conversion thru table
;
Methode2:
	ld	ix,tentbl	; Init table
	ld	c,1		; Set zero flag
dotpos:
	ld	e,(ix)		; Get divisor
	inc	ix
	ld	d,(ix)
	inc	ix
	ld	b,-1		; Clear digit
dotdiv:
	inc	b		; Count digits
	or	a
	sbc	hl,de		; Divide
	jr	nc,dotdiv
	add	hl,de		; Make > 0
	xor	a
	or	b		; Test zero digit
	jr	nz,dotstr
	or	c		; Clear leading zero
	jr	nz,dotbyp
dotstr:
	ld	c,0		; Clear zero flag
	or	'0'		; Make ASCII
	call	APUT		; Put anywhere
dotbyp:
	ld	a,e		; Test end of table
	cp	10
	jr	nz,dotpos
	ld	a,l
	or	'0'
	call	APUT		; Put anywhere
	ret
;
tentbl:
	dw	10000
	dw	 1000
	dw	  100
	dw	   10

;
; Conversion thru table
;
Methode3:
	ld	ix,tentbl	; Init table
	ld	bc,256*5+'0'	; Set length
dotpos:
	ld	e,(ix+0)	; Get divisor
	ld	d,(ix+1)
	ld	a,'0'-1		; Clear digit
	or	a
dotdiv:
	inc	a		; Count digits
	sbc	hl,de		; Divide
	jr	nc,dotdiv
	add	hl,de		; Make > 0
	cp	c		; Test zero digit
	jr	nz,dotstr
	ld	a,' '
	inc	c		; Clear leading zero
dotstr:
	call	APUT		; Put anywhere
	dec	c
	inc	ix
	inc	ix
	djnz	dotpos
	ret
;
tentbl:
	dw	10000
	dw	1000
	dw	100
	dw	10
	db	1

;
; Division by negative constants
;
Methode4:
	ld	d,0		; Set no leading zero
	ld	e,5		; Set max number of digits
	call	divpow10	; Get digits
	dw	-10000
	call	divpow10
	dw	-1000
	call	divpow10
	dw	-100
	call	divpow10
	dw	-10
	ld	d,'0'		; Allow zeroes now
	call	divpow10
	dw	-1
	inc	e
trail:
	dec	e		; Test all digits converted
	ret	z		; Yeap
	ld	a,' '
	call	APUT		; Put trailing blanks anywhere
	jr	trail
;
; Output quotient as decimal number [HL DIV <SP>]
;
divpow10:
	ex	(sp),hl
	ld	c,(hl)		; Fetch divisor
	inc	hl
	ld	b,(hl)
	inc	hl
	ex	(sp),hl
	ld	a,'0'		; Init digit
divloop:
	push	hl		; Save value
	add	hl,bc		; Divide
	jr	nc,divend	; Get result
	inc	a		; Advance quotient
	inc	sp		; Delete remainder
	inc	sp
	jr	divloop
divend:
	pop	hl		; Get back remainder
	cp	'0'		; Test possible leading zero
	jr	nz,not0		; Nope
	ld	a,d		; Get state of leading zero
	jr	tst0		; Test leading zero allowed
not0:
	ld	d,'0'		; Set no leading zero
tst0:
	cp	0		; Test leading zero allowed
	ret	z		; Nope
	call	APUT		; Put anywhere
	dec	e		; Count down remaining length
	ret

;
; Division by positive constants
;
Methode5:
	ld	b,0		; Init flag
	ld	de,10000
	call	divpow10	; Start with 10000s
	ld	de,1000
	call	divpow10	; Then 1000s
	ld	de,100
	call	divpow10	; Then 100s
	ld	e,10
	call	divpow10	; Then 10s
	ld	a,l		; Get remainder
	jr	lastdig
divpow10:
	xor	a		; Clear quotient
divloop:
	inc	a		; Advance quotient
	sbc	hl,de		; Divide
	jr	nc,divloop	; Still positive
	add	hl,de		; Fix for last number
	inc	b		; Access flag
	dec	a		; Test zero digit
	jr	nz,lastdig	; Nope, so store result
	dec	b		; Test flag
	ret	z		; No leading zeroes
lastdig:
	add	a,'0'		; Make ASCII
	call	APUT		; Put anywhere
	ret

;
; Through BCD
;
Methode6:
	ex	de,hl
	ld	a,0		
	ld	b,3
	ld	hl,DecBuff
HexIni:
	ld	(hl),a		; Clear resulting bytes
	inc	hl
	djnz	HexIni
	ld	b,16		; Set bit length
HexDiv:
	ex	de,hl
	add	hl,hl		; Get most significant bit
	ex	de,hl
	push	bc
	ld	b,3
	ld	hl,DecBuff
HexBCD:
	ld	a,(hl)
	adc	a,(hl)		; Add most significant bit
	daa			; Convert to BCD
	ld	(hl),a
	inc	hl
	djnz	HexBCD
	pop	bc
	djnz	HexDiv
	ld	b,3		; Set number of bytes
	ld	c,3*2		; Set number of characters
	ld	hl,DecBuff+2	; Pointer to highest BCD
nbyte:
	ld	a,(hl)		; Load BCD
	call	ByteOut		; Store it
	dec	hl
	djnz	nbyte
	ret
;
; Store BCD Byte in Accu
;
ByteOut:
	push	af
	srl	a		; Extract high bits
	srl	a
	srl	a
	srl	a
	call	DecOut		; Store it
	pop	af
DecOut:
	and	00001111b	; Mask bits
	or	'0'
	dec	c		; Test if last place
	jr	z,TTYOut	; Then bypass zero testing
	bit	7,c		; Test leading zero
	jr	nz,TTYOut	; Nope
	cp	'0'		; This one zero?
	jr	z,Zero		; Ignore if so
	set	7,c		; Mark no zero
Zero:
	jr	nz,TTYOut	; Store it
	ld	a,' '		; Store leading zero as blank
TTYOut:
	call	APUT		; Put anywhere
	ret
;
DecBuff:
	ds	3

Werner Cirsovius Compiled since January 2008