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:
- Register
HL holds the binary value
- Registers will not be saved
- 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.
|
|
;
; 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