Is there any ASM snippet to port in ascii a 32 bit long ?
I have seen z80 ASM for 16 bit int to ascii but no 32 bit code...
Entrar ou registrar-se para comentar
Is there any ASM snippet to port in ascii a 32 bit long ?
I have seen z80 ASM for 16 bit int to ascii but no 32 bit code...
24 bits enough?
--------------- snip -----------
; Routine for converting a 24-bit binary number to decimal
; In: E:HL = 24-bit binary number (0-16777215)
; Out: DE:HL = 8 digit decimal form (packed BCD)
; Changes: AF, BC, DE, HL & IX
; by Alwin Henseler
LD C,E
PUSH HL
POP IX ; input value in C:IX
LD HL,1
LD D,H
LD E,H ; start value corresponding with 1st 1-bit
LD B,24 ; bitnr. being processed + 1
FIND1: ADD IX,IX
RL C ; shift bit 23-0 from C:IX into carry
JR C,NEXTBIT
DJNZ FIND1 ; find highest 1-bit
; All bits 0:
RES 0,L ; least significant bit not 1 after all ..
RET
DBLLOOP: LD A,L
ADD A,A
DAA
LD L,A
LD A,H
ADC A,A
DAA
LD H,A
LD A,E
ADC A,A
DAA
LD E,A
LD A,D
ADC A,A
DAA
LD D,A ; double the value found so far
ADD IX,IX
RL C ; shift next bit from C:IX into carry
JR NC,NEXTBIT ; bit = 0 -> don't add 1 to the number
SET 0,L ; bit = 1 -> add 1 to the number
NEXTBIT: DJNZ DBLLOOP
RET
--------------- snip -----------
Straight from my time-tested toolbox
If you want bigger numbers: let me know. I also have a routine that can do up to 64 bit numbers (20 digits decimal) and produces ready-for-printing result, but it's quite a bit longer. Probably did it once just to see how easy it was to expand, or to have something that can take anything you throw at it...
hummm
I was expecting something different .... thanks anyway
Scores need only Add and Sub. Maybe it is safer to move to BCD math directly
RetroTechie
I need to convert a 32bit number from DE:HL to a string inRAM pointed by BC
can you share your code for ready for printing results?
I found this routine...
;### CLCN32 -> Converts 32Bit-Value in ASCII-String (terminated by 0)
;### Input DE,IX=32bit value, IY=destination address
;### Output IY=last char in destination string
;### Destroyed AF,BC,DE,HL,IX
clcn32t dw 1,0, 10,0, 100,0, 1000,0, 10000,0
dw #86a0,1, #4240,#f, #9680,#98, #e100,#5f5, #ca00,#3b9a
clcn32z ds 4
clcn32 ld (clcn32z),ix
ld (clcn32z+2),de
ld ix,clcn32t+36
ld b,9
ld c,0
clcn321 ld a,"0"
or a
clcn322 ld e,(ix+0):ld d,(ix+1):ld hl,(clcn32z): sbc hl,de:ld (clcn32z),hl
ld e,(ix+2):ld d,(ix+3):ld hl,(clcn32z+2):sbc hl,de:ld (clcn32z+2),hl
jr c,clcn325
inc c
inc a
jr clcn322
clcn325 ld e,(ix+0):ld d,(ix+1):ld hl,(clcn32z): add hl,de:ld (clcn32z),hl
ld e,(ix+2):ld d,(ix+3):ld hl,(clcn32z+2):adc hl,de:ld (clcn32z+2),hl
ld de,-4
add ix,de
inc c
dec c
jr z,clcn323
ld (iy+0),a
inc iy
clcn323 djnz clcn321
ld a,(clcn32z)
add "0"
ld (iy+0),a
ld (iy+1),0
ret
...but I don't know (and don't think so
), if it's optimized in any way ( I didn't really need it to be optimized up to now).
Now tested and working
; HL:DE INPUT ; BC POINTS TO OUTPUT long2ascii: ; HL = HIGH WORD PUSH DE EXX POP HL ; HL' = LOW WORD EXX LD E,C LD D,B LD BC,-1000000000/0x10000 -1 EXX LD BC,-1000000000&0xFFFF EXX CALL NUM1 LD BC,-100000000/0x10000 -1 EXX LD BC,-100000000&0xFFFF EXX CALL NUM1 LD BC,-10000000/0x10000 -1 EXX LD BC,-10000000&0xFFFF EXX CALL NUM1 LD BC,-1000000/0x10000 -1 EXX LD BC,-1000000&0xFFFF EXX CALL NUM1 LD BC,-100000/0x10000 -1 EXX LD BC,-100000&0xFFFF EXX CALL NUM1 LD BC,-10000/0x10000 -1 EXX LD BC,-10000&0xFFFF EXX CALL NUM1 LD BC,-1000/0x10000 -1 EXX LD BC,-1000&0xFFFF EXX CALL NUM1 LD BC,-100/0x10000 -1 EXX LD BC,-100&0xFFFF EXX CALL NUM1 LD BC,-10/0x10000 -1 EXX LD BC,-10&0xFFFF EXX CALL NUM1 LD BC,-1/0x10000 -1 EXX LD BC,-1&0xFFFF EXX CALL NUM1 RET NUM1: LD A,'0'-1 ; '0' IN THE TILESET NUM2: INC A EXX add HL,BC ; low word EXX ADC HL,BC ; high word jp C,NUM2 EXX SBC HL,BC ; low word EXX SBC HL,BC ; high word LD (DE),A INC DE RET












Looks like a pretty tight routine, Prodatron (if it works, that is).
Sorry for the delay... I was translating comments, then my employer called and turned my day off into a work day 
Now, onto the mother of all binary-to-printable routines:
------------ snip ------------
; Combined routine for conversion of different sized binary numbers into
; directly printable ASCII(Z)-string
; Input value in registers, number size and -related to that- registers to fill
; is selected by calling the correct entry:
;
; entry inputregister(s) decimal value 0 to:
; B2D8 A 255 (3 digits)
; B2D16 HL 65535 5 "
; B2D24 E:HL 16777215 8 "
; B2D32 DE:HL 4294967295 10 "
; B2D48 BC:DE:HL 281474976710655 15 "
; B2D64 IX:BC:DE:HL 18446744073709551615 20 "
;
; The resulting string is placed into a small buffer attached to this routine,
; this buffer needs no initialization and can be modified as desired.
; The number is aligned to the right, and leading 0's are replaced with spaces.
; On exit HL points to the first digit, (B)C = number of decimals
; This way any re-alignment / postprocessing is made easy.
; Changes: AF,BC,DE,HL,IX
; P.S. some examples below
; by Alwin Henseler
B2D8: LD H,0
LD L,A
B2D16: LD E,0
B2D24: LD D,0
B2D32: LD BC,0
B2D48: LD IX,0 ; zero all non-used bits
B2D64: LD (B2DINV),HL
LD (B2DINV+2),DE
LD (B2DINV+4),BC
LD (B2DINV+6),IX ; place full 64-bit input value in buffer
LD HL,B2DBUF
LD DE,B2DBUF+1
LD (HL)," "
B2DFILC: EQU $-1 ; address of fill-character
LD BC,18
LDIR ; fill 1st 19 bytes of buffer with spaces
LD (B2DEND-1),BC ;set BCD value to "0" & place terminating 0
LD E,1 ; no. of bytes in BCD value
LD HL,B2DINV+8 ; (address MSB input)+1
LD BC,#0909
XOR A
B2DSKP0: DEC B
JR Z,B2DSIZ ; all 0: continue with postprocessing
DEC HL
OR (HL) ; find first byte <>0
JR Z,B2DSKP0
B2DFND1: DEC C
RLA
JR NC,B2DFND1 ; determine no. of most significant 1-bit
RRA
LD D,A ; byte from binary input value
B2DLUS2: PUSH HL
PUSH BC
B2DLUS1: LD HL,B2DEND-1 ; address LSB of BCD value
LD B,E ; current length of BCD value in bytes
RL D ; highest bit from input value -> carry
B2DLUS0: LD A,(HL)
ADC A,A
DAA
LD (HL),A ; double 1 BCD byte from intermediate result
DEC HL
DJNZ B2DLUS0 ; and go on to double entire BCD value (+carry!)
JR NC,B2DNXT
INC E ; carry at MSB -> BCD value grew 1 byte larger
LD (HL),1 ; initialize new MSB of BCD value
B2DNXT: DEC C
JR NZ,B2DLUS1 ; repeat for remaining bits from 1 input byte
POP BC ; no. of remaining bytes in input value
LD C,8 ; reset bit-counter
POP HL ; pointer to byte from input value
DEC HL
LD D,(HL) ; get next group of 8 bits
DJNZ B2DLUS2 ; and repeat until last byte from input value
B2DSIZ: LD HL,B2DEND ; address of terminating 0
LD C,E ; size of BCD value in bytes
OR A
SBC HL,BC ; calculate address of MSB BCD
LD D,H
LD E,L
SBC HL,BC
EX DE,HL ; HL=address BCD value, DE=start of decimal value
LD B,C ; no. of bytes BCD
SLA C ; no. of bytes decimal (possibly 1 too high)
LD A,"0"
RLD ; shift bits 4-7 of (HL) into bit 0-3 of A
CP "0" ; (HL) was > 9h?
JR NZ,B2DEXPH ; if yes, start with recording high digit
DEC C ; correct number of decimals
INC DE ; correct start address
JR B2DEXPL ; continue with converting low digit
B2DEXP: RLD ; shift high digit (HL) into low digit of A
B2DEXPH: LD (DE),A ; record resulting ASCII-code
INC DE
B2DEXPL: RLD
LD (DE),A
INC DE
INC HL ; next BCD-byte
DJNZ B2DEXP ; and go on to convert each BCD-byte into 2 ASCII
SBC HL,BC ; return with HL pointing to 1st decimal
RET
B2DINV: DS 8 ; space for 64-bit input value (LSB first)
B2DBUF: DS 20 ; space for 20 decimal digits
B2DEND: DS 1 ; space for terminating 0
END
EXAMPLES
--------
(In these examples, it is assumed there exists a subroutine PRINT, that
prints a string (terminated by a 0-byte) starting at address [HL] )
Print 1 byte, as follows:
20
7
145 etc.
by: LD A,byte
CALL B2D8
LD HL,B2DEND-3
CALL PRINT
Print a 24-bit value, as follows:
9345
76856366
534331
by: LD E,bit23-16
LD HL,bit15-0
CALL B2D24
CALL PRINT
Print a 48-bit value, like
14984366484
49
123456789012345
3155556 etc.
by:
LD BC,bit47-32
LD DE,bit31-16
LD HL,bit15-0
CALL B2D48
LD HL,B2DEND-15
CALL PRINT
....... ETC , ETC , ETC , ...... --------------- snip -------------------
As I said: it's looonnggg. It should be straightforward to trim it down in case you only need a 32-bit conversion. But there's not much point, the routine above is reasonably efficient in avoiding unnecessary work. If you don't believe me: fire up a debugger, throw eg. a 16 bit number at it, and trace the steps it goes through. It is known working, but can't say I used it much. More like a 'nice to have in my toolbox'.
Btw. if you're using this for score-keeping in an action game, then I suggest you move to (packed?) BCD arithmetic. Almost as simple to add/subtract as binary, and conversion to ASCII is trivial (=good when you don't want to affect gameplay).
Great stuff! Thanx for posting, RetroTechie!
RetroTechie this code is pure gold
Thanks!!!
BTW, yes, i am doing the score system of an action game and I was just wandering about the cpu load....
Just in case, do you know where I can wind some tested BCD asm routines for add, sub and print of 10 digits numbers?
Actually I've never used DAA....
ps
code from this site seemd broken
http://icarus.ticalc.org/articles/z80_faq.html
as no carry is passed between digits in different bytes
Actually I've never used DAA....
DAA (Decimal Adjust Accumulator) works best with packed BCD arithmetic (2 digits 0-9 encoded in the 2 halves -nibbles- of an 8-bit number). So each byte encodes 00-99 decimal number (actually, the hex representation matches the decimal number).
When you do an addition, a nibble may go into 10-15 range (A-F hex). Now if you execute DAA immediately after that addition, it will leave that nibble alone if in 0-9 range, or subtract 10 if in 10-15 range, and pass any carry along. That is: for low nibble, pass carry to high nibble, for high nibble, pass to carry flag. IIRC it uses various flags (P/V, carry) to 'do the right thing' in various situations.
Basically you just do 8-bits add as usual, but throw in a DAA right after each add instruction (to bring temporary result back to 00-99), and you process the carry flag as usual. AFAIK this works for subtractions too. Just remember your bytes now represent 00-99 values, and you have to use A register for the actual arithmetic (DAA only works on A register).
Nicest use I ever saw, was for an insanely short 0-A hex -> "0"-"A" ASCII conversion (4 Z80 instructions!). I'll see if I can find that snippet somewhere... or maybe someone else here knows that sequence I'm referring to?
Don't you have an account yet? Become an MSX-friend and register an account!
