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
    ;
    ;================================================================================
    	.end

Last page update: March 28, 2010.