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.