Convert ASCII Number String to 32-bit Binary by BigDumbDinosaur
[Up to Source Code Repository]


Convert ASCII Number String to 32-bit Binary

This 6502 assembly language program converts a null-terminated ASCII number string into a 32-bit unsigned binary value in little-endian format. It can accept a number in binary, octal, decimal or hexadecimal format.

;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;*                                                                             *
;*                CONVERT ASCII NUMBER STRING TO 32-BIT BINARY                 *
;*                                                                             *
;*                             by BigDumbDinosaur                              *
;*                                                                             *
;* This 6502 assembly language program converts a null-terminated ASCII number *
;* string into a 32-bit unsigned binary value in little-endian format.  It can *
;* accept a number in binary, octal, decimal or hexadecimal format.            *
;*                                                                             *
;* --------------------------------------------------------------------------- *
;*                                                                             *
;* 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'll get your money's worth.                                    *
;*                                                                             *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;	Calling Syntax:
;
;		ldx #<numstr
;		ldy #>numstr
;		jsr strbin
;		bcs error
;
;	All registers are modified.  The result of the conversion is left in
;	location PFAC in unsigned, little-endian format (see source code).
;	The contents of PFAC are undefined if strbin exits with an error.
;	The maximum number that can be converted is 4,294,967,295 or (2^32)-1.
;
;	numstr must point to a null-terminated character string in the format:
;
;		[%|@|$]DDD...DDD
;
;	where %, @ or $ are optional radices specifying, respectively, base-2,
;	base-8 or base-16.  If no radix is specified, base-10 is assumed.
;
;	DDD...DDD represents the characters that comprise the number that is
;	to be converted.  Permissible values for each instance of D are:
;
;		Radix  Description  D - D
;		-------------------------
;		  %    Binary       0 - 1
;		  @    Octal        0 - 7
;		 None  Decimal      0 - 9
;		  $    Hexadecimal  0 - 9
;		                    A - F
;		-------------------------
;
;	Conversion is not case-sensitive.  Leading zeros are permissible, but
;	not leading blanks.  The maximum string length including the null
;	terminator is 127.  An error will occur if a character in the string
;	to be converted is not appropriate for the selected radix, the con-
;	verted value exceeds $FFFFFFFF or an undefined radix is specified.
;
;================================================================================
;
;ATOMIC CONSTANTS
;
_origin_ =$02000               ;assembly address
;
;	------------------------------------------
;	Define the above to suit your application.
;	------------------------------------------
;
a_maskuc =%01011111            ;case conversion mask
a_hexnum ='A'-'9'-1            ;hex to decimal difference
n_radix  =4                    ;number of supported radixes
s_fac    =4                    ;binary accumulator size
;
;================================================================================
;
;ZERO PAGE STORAGE
;
ptr01    =$00                  ;input string pointer
stridx   =ptr01+2              ;string index
pfac     =stridx+1             ;primary accumulator
sfac     =pfac+s_fac           ;secondary accumulator
;
;	------------------------------------------------------
;	Define the above to suit your application.  Moving the
;	accumulators to absolute storage will result in an
;	approximate 20 percent increase in execution time &
;	will require some program restructuring to avoid out-
;	of-range relative branches.
;	------------------------------------------------------
;
;================================================================================
;
;CONVERT NULL-TERMINATED STRING TO 32 BIT BINARY
;
         *=_origin_
;
strbin   stx ptr01             ;save string pointer LSB
         sty ptr01+1           ;save string pointer MSB
         lda #0
         ldx #s_fac-1          ;accumulator size
;
strbin01 sta pfac,x            ;clear
         dex
         bpl strbin01
;
;	------------------------
;	process radix if present
;	------------------------
;
         tay                   ;starting string index
         clc                   ;assume no error for now
         lda (ptr01),y         ;get a char
         bne strbin02
;
         rts                   ;null string, so exit
;
strbin02 ldx #n_radix-1
;
strbin03 cmp radxtab,x         ;recognized radix?
         beq strbin04          ;yes
;
         dex
         bpl strbin03          ;try next
;
         stx radxflag          ;assuming decimal...
         inx                   ;which might be wrong
;
strbin04 lda basetab,x         ;number bases table
         sta valdnum           ;set valid numeral range
         lda bitstab,x         ;get bits per digit
         sta bitsdig           ;store
         txa                   ;was radix specified?
         beq strbin06          ;no
;
         iny                   ;move past radix
;
strbin05 sty stridx            ;save string index
;
;	--------------------------------
;	process number portion of string
;	--------------------------------
;
strbin06 clc                   ;assume no error for now
         lda (ptr01),y         ;get numeral
         beq strbin17          ;end of string
;
         inc stridx            ;point to next
         cmp #'a'              ;check char range
         bcc strbin07          ;not ASCII LC
;
         cmp #'z'+1
         bcs strbin08          ;not ASCII LC
;
         and #a_maskuc         ;do case conversion
;
strbin07 sec
;
strbin08 sbc #'0'              ;change numeral to binary
         bcc strbin16          ;numeral > 0
;
         cmp #10
         bcc strbin09          ;numeral is 0-9
;
         sbc #a_hexnum         ;do a hex adjust
;
strbin09 cmp valdnum           ;check range
         bcs strbin17          ;out of range
;
         sta curntnum          ;save processed numeral
         bit radxflag          ;working in base 10?
         bpl strbin11          ;no
;
;	-----------------------------------------------------------
;	Prior to combining the most recent numeral with the partial
;	result, it is necessary to left-shift the partial result
;	result 1 digit.  The operation can be described as N*base,
;	where N is the partial result & base is the number base.
;	N*base with binary, octal & hex is a simple repetitive
;	shift.  A simple shift won't do with decimal, necessitating
;	an (N*8)+(N*2) operation.  PFAC is copied to SFAC to gener-
;	ate the N*2 term.
;	-----------------------------------------------------------
;
         ldx #0
         ldy #s_fac            ;accumulator size
         clc
;
strbin10 lda pfac,x            ;N
         rol                   ;N=N*2
         sta sfac,x
         inx
         dey
         bne strbin10
;
         bcs strbin17          ;overflow = error
;
strbin11 ldx bitsdig           ;bits per digit
;
strbin12 asl pfac              ;compute N*base for binary,...
         rol pfac+1            ;octal &...
         rol pfac+2            ;hex or...
         rol pfac+3            ;N*8 for decimal
         bcs strbin17          ;overflow
;
         dex
         bne strbin12          ;next shift
;
         bit radxflag          ;check base
         bpl strbin14          ;not decimal
;
;	-------------------
;	compute (N*8)+(N*2)
;	-------------------
;
         ldx #0                ;accumulator index
         ldy #s_fac
;
strbin13 lda pfac,x            ;N*8
         adc sfac,x            ;N*2
         sta pfac,x            ;now N*10
         inx
         dey
         bne strbin13
;
         bcs strbin17          ;overflow
;
;	-------------------------------------
;	add current numeral to partial result
;	-------------------------------------
;
strbin14 clc
         lda pfac              ;N
         adc curntnum          ;N=N+D
         sta pfac
         ldx #1
         ldy #s_fac-1
;
strbin15 lda pfac,x
         adc #0                ;account for carry
         sta pfac,x
         inx
         dey
         bne strbin15
;
         bcs strbin17          ;overflow
;
;	----------------------
;	ready for next numeral
;	----------------------
;
         ldy stridx            ;string index
         bpl strbin06          ;get another numeral
;
;	----------------------------------------------
;	if string length > 127 fall through with error
;	----------------------------------------------
;
strbin16 sec                   ;flag an error
;
strbin17 rts                   ;done
;
;================================================================================
;
;CONVERSION TABLES
;
basetab  .byte 10,2,8,16       ;number bases per radix
bitstab  .byte 3,1,3,4         ;bits per digit per radix
radxtab  .byte " %@$"          ;valid radix symbols
;
;================================================================================
;
;DYNAMIC STORAGE
;
bitsdig  *=*+1                 ;bits per digit
curntnum *=*+1                 ;numeral being processed
radxflag *=*+1                 ;$80 = processing base-10
valdnum  *=*+1                 ;valid range +1 for selected radix
;
;================================================================================
	.end
Last page update: January 30, 2010.