Convert 32-bit Binary to ASCII Number String by BigDumbDinosaur
[Up to Source Code Repository]
Convert ASCII Number String to 32-bit Binary
This program converts 32-bit binary back to an ASCII string. It is a companion to Convert ASCII Number String to 32-bit Binary.
A subroutine in this program makes use of the MPU's decimal mode. Since decimal mode is not cleared following an interrupt on an NMOS processor, there are notes in the code warning about it. Please see them below.
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ;* * ;* CONVERT 32-BIT BINARY TO ASCII NUMBER STRING * ;* * ;* by BigDumbDinosaur * ;* * ;* This 6502 assembly language program converts a 32-bit unsigned binary value * ;* into a null-terminated ASCII string whose format may be in binary, octal, * ;* decimal or hexadecimal. * ;* * ;* --------------------------------------------------------------------------- * ;* * ;* Copyright (C)1985 by BCS Technology Limited. All rights reserved. * ;* * ;* Permission is hereby granted to copy and redistribute this software, prov- * ;* ided this copyright notice remains in the source code & proper attribution * ;* is given. Any redistribution, regardless of form, must be at no charge to * ;* the end user. This code MAY NOT be incorporated into any package intended * ;* for sale unless written permission has been given by the copyright holder. * ;* * ;* THERE IS NO WARRANTY OF ANY KIND WITH THIS SOFTWARE. It's free, so no mat- * ;* ter what, you're getting a great deal. * ;* * ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; CALLING SYNTAX: ; ; LDA #RADIX ;radix character, see below ; LDX #<OPERAND ;binary value address LSB ; LDY #>OPERAND ;binary value address MSB ; (ORA #%10000000) ;radix suppression, see below ; JSR BINSTR ;perform conversion ; STX ZPPTR ;save string address LSB ; STY ZPPTR+1 ;save string address MSB ; TAY ;string length ; LOOP LDA (ZPPTR),Y ;copy string to... ; STA MYSPACE,Y ;safe storage, will include... ; DEY ;the terminator ; BPL LOOP ; ; CALLING PARAMETERS: ; ; .A Conversion radix, which may be any of the following: ; ; '%' Binary. ; '@' Octal. ; '$' Hexadecimal. ; ; If the radix is not one of the above characters decimal will be ; assumed. Binary, octal & hex conversion will prepend the radix ; character to the string. To suppress this feature set bit 7 of ; the radix. ; ; .X/.Y The address of the 32-bit binary value (operand) that is to be ; converted. The operand must be in little-endian format. ; ; REGISTER RETURNS: ; ; .A The printable string length. The exact length will depend on ; the radix that has been selected, whether the radix is to be ; prepended to the string & the number of significant digits. ; Maximum possible printable string lengths for each radix type ; are as follows: ; ; % Binary 33 ; @ Octal 12 ; Decimal 11 ; $ Hex 9 ; ; .X/.Y The LSB/MSB address at which the null-terminated conversion ; string will be located. The string will be assembled into a ; statically allocated buffer and should be promptly copied to ; user-defined safe storage. ; ; .C The carry flag will always be clear. ; ; APPROXIMATE EXECUTION TIMES in CLOCK CYCLES: ; ; Binary 5757 ; Octal 4533 ; Decimal 13390 ; Hex 4373 ; ; The above execution times assume the operand is $FFFFFFFF, the radix ; is to be prepended to the conversion string & all workspace other than ; the string buffer is on zero page. Relocating ZP workspace to absolute ; memory will increase execution time approximately 8 percent. ; ;================================================================================ ; ;ATOMIC CONSTANTS ; _origin_ =$02000 ;assembly address _zpage_ =$00 ;start of ZP storage ; ; ------------------------------------------ ; Modify the above to suit your application. ; ------------------------------------------ ; a_hexdec ='A'-'9'-2 ;hex to decimal difference m_bits =32 ;operand bit size m_cbits =48 ;workspace bit size m_strlen =m_bits+1 ;maximum printable string length n_radix =4 ;number of supported radices s_pfac =m_bits/8 ;primary accumulator size s_ptr =2 ;pointer size s_wrkspc =m_cbits/8 ;conversion workspace size ; ;================================================================================ ; ;ZERO PAGE ASSIGNMENTS ; ptr01 =_zpage_ ;string storage pointer ; ; --------------------------------- ; The following may be relocated to ; absolute storage if desired. ; --------------------------------- ; pfac =ptr01+s_ptr ;primary accumulator wrkspc01 =pfac+s_pfac ;conversion... wrkspc02 =wrkspc01+s_wrkspc ;workspace formflag =wrkspc02+s_wrkspc ;string format flag radix =formflag+1 ;radix index stridx =radix+1 ;string buffer index ; ;================================================================================ ; ;CONVERT 32-BIT BINARY TO NULL-TERMINATED ASCII NUMBER STRING ; ; ---------------------------------------------------------------- ; WARNING! If this code is run on an NMOS MPU it will be necessary ; to disable IRQs during binary to BCD conversion unless ; the target system's IRQ handler clears decimal mode. ; Refer to the FACBCD subroutine. ; ---------------------------------------------------------------- ; *=_origin_ ; binstr stx ptr01 ;operand pointer LSB sty ptr01+1 ;operand pointer MSB tax ;protect radix ldy #s_pfac-1 ;operand size ; binstr01 lda (ptr01),y ;copy operand to... sta pfac,y ;workspace dey bpl binstr01 ; iny sty stridx ;initialize string index ; ; -------------- ; evaluate radix ; -------------- ; txa ;radix character asl ;extract format flag &... ror formflag ;save it lsr ;extract radix character ldx #n_radix-1 ;total radices ; binstr03 cmp radxtab,x ;recognized radix? beq binstr04 ;yes ; dex bne binstr03 ;try next ; ; ------------------------------------ ; radix not recognized, assume decimal ; ------------------------------------ ; binstr04 stx radix ;save radix index for later txa ;converting to decimal? bne binstr05 ;no ; ; ------------------------------ ; prepare for decimal conversion ; ------------------------------ ; jsr facbcd ;convert operand to BCD lda #0 beq binstr09 ;skip binary stuff ; ; ------------------------------------------- ; prepare for binary, octal or hex conversion ; ------------------------------------------- ; binstr05 bit formflag bmi binstr06 ;no radix symbol wanted ; lda radxtab,x ;radix table sta strbuf ;prepend to string inc stridx ;bump string index ; binstr06 ldx #0 ;operand index ldy #s_wrkspc-1 ;workspace index ; binstr07 lda pfac,x ;copy operand to... sta wrkspc01,y ;workspace in... dey ;big-endian order inx cpx #s_pfac bne binstr07 ; lda #0 ; binstr08 sta wrkspc01,y ;pad workspace dey bpl binstr08 ; ; ---------------------------- ; set up conversion parameters ; ---------------------------- ; binstr09 sta wrkspc02 ;initialize byte counter ldy radix ;radix index lda numstab,y ;numerals in string sta wrkspc02+1 ;set remaining numeral count lda bitstab,y ;bits per numeral sta wrkspc02+2 ;set lda lzsttab,y ;leading zero threshold sta wrkspc02+3 ;set ; ; -------------------------- ; generate conversion string ; -------------------------- ; binstr10 lda #0 ldy wrkspc02+2 ;bits per numeral ; binstr11 ldx #s_wrkspc-1 ;workspace size clc ;avoid starting carry ; binstr12 rol wrkspc01,x ;shift out a bit... dex ;from the operand or... bpl binstr12 ;BCD conversion result ; rol ;bit to .A dey bne binstr11 ;more bits to grab ; tay ;if numeral isn't zero... bne binstr13 ;skip leading zero tests ; ldx wrkspc02+1 ;remaining numerals cpx wrkspc02+3 ;leading zero threshold bcc binstr13 ;below it, must convert ; ldx wrkspc02 ;processed byte count beq binstr15 ;discard leading zero ; binstr13 cmp #10 ;check range bcc binstr14 ;is 0-9 ; adc #a_hexdec ;apply hex adjust ; binstr14 adc #'0' ;change to ASCII ldy stridx ;string index sta strbuf,y ;save numeral in buffer inc stridx ;next buffer position inc wrkspc02 ;bytes=bytes+1 ; binstr15 dec wrkspc02+1 ;numerals=numerals-1 bne binstr10 ;not done ; ; ----------------------- ; terminate string & exit ; ----------------------- ; lda #0 ldx stridx ;printable string length sta strbuf,x ;terminate string txa ldx #<strbuf ;converted string LSB ldy #>strbuf ;converted string MSB clc ;all okay rts ; ;================================================================================ ; ;CONVERT PFAC INTO BCD ; ; --------------------------------------------------------------- ; Uncomment noted instructions if this code is to be used on an ; NMOS system whose interrupt handlers do not clear decimal mode. ; --------------------------------------------------------------- ; facbcd ldx #s_pfac-1 ;primary accumulator size -1 ; facbcd01 lda pfac,x ;value to be converted pha ;protect dex bpl facbcd01 ;next ; lda #0 ldx #s_wrkspc-1 ;workspace size ; facbcd02 sta wrkspc01,x ;clear final result sta wrkspc02,x ;clear scratchpad dex bpl facbcd02 ; inc wrkspc02+s_wrkspc-1 ;php ;!!! uncomment for NMOS MPU !!! ;sei ;!!! uncomment for NMOS MPU !!! sed ;select decimal mode ldy #m_bits-1 ;bits to convert -1 ; facbcd03 ldx #s_pfac-1 ;operand size clc ;no carry at start ; facbcd04 ror pfac,x ;grab LS bit in operand dex bpl facbcd04 ; bcc facbcd06 ;LS bit clear ; clc ldx #s_wrkspc-1 ; facbcd05 lda wrkspc01,x ;partial result adc wrkspc02,x ;scratchpad sta wrkspc01,x ;new partial result dex bpl facbcd05 ; clc ; facbcd06 ldx #s_wrkspc-1 ; facbcd07 lda wrkspc02,x ;scratchpad adc wrkspc02,x ;double &... sta wrkspc02,x ;save dex bpl facbcd07 ; dey bpl facbcd03 ;next operand bit ; ;plp ;!!! uncomment for NMOS MPU !!! ldx #0 ; facbcd08 pla ;operand sta pfac,x ;restore inx cpx #s_pfac bne facbcd08 ;next ; rts ; ;================================================================================ ; ;PER RADIX CONVERSION TABLES ; bitstab .byte 4,1,3,4 ;bits per numeral lzsttab .byte 2,9,2,3 ;leading zero suppression thresholds numstab .byte 12,48,16,12 ;maximum numerals radxtab .byte 0,"%@$" ;recognized symbols ; ;================================================================================ ; ;STATIC STORAGE ; strbuf *=*+m_strlen+1 ;conversion string buffer ; ;================================================================================ .endLast page update: March 28, 2010.