I have a 16-bit assembly 'binary to ascii' routine and a 'ascii to binary' routine that both do conversions of max size
double-word numbers (i.e, convert binary input =< 0ffffh 0ffffh passed in ax/dx registers to get ascii output returned
in buffer =< '4294967295', OR convert ascii input passed in buffer =< '4294967295' to get binary output =< 0ffffh 0ffffh
returned in ax/dx LSW/MSW).
I now need routines be able to handle ascii numbers =< '999999999999' or 00e8h d4a5h 0fffh in binary, or basicly
3 words iin size (althought I'll really only need to use the lower order byte of the additional 3rd word). With this size number
I obviously would need to use the lower order byte of some other register, say bx for the binary convertion output
to registers, i.e. if passed ascii input of '999999999999', output would be returned as ax=0fffh, dx=0d4a5h, bx=00e8h.
And the reverse in other routijne, if passed binary input =< ax=0fffh, dx=0d4a5h, bx=00e8h, outut returned would be =< '999999999999'
Anybody got any .asm routines that will accomplish these 3-word binary/asciii conversions that they want to share
with me?
Thanks in advance - Dale
well - offhand, i don't have a 16-bit version
but, as a suggestion, you might like "Horner's Rule" (or Ling Long Kai Fang, as i prefer to call it)
you should be able to find references with google
as you read each byte, AND it with 0Fh to convert it from ASCII to binary, then....
basically, you grab the first byte in the string, multiply it by 10 (provided it isn't the last byte), then store that as the accumlator
then grab the next byte and repeat
when you grab the last byte and add it to the accumulator, do not multiply by 10 - you are done
the trouble you will have with such large numbers in 16-bit is multiplying by 10
you can use multiple precision multiplication, or shift and add
for this size, i would think shift and add might be fastest
shift the entire accumulator left by 1 bit (this is accum X 2)
make a copy of the entire accumulator
shift one of the 2 copies left by 2 more bits (this is accum X 8)
add the 2 copies together and the total represents the accumulator X 10
as you can see, you need 5 16-bit registers, one of which is split in half
you might use BL:DX:AX for one
and BH:SI:DI for the other
multiply the contents of BL:DX:AX by 10
;multiply the accumulator by 2
shl ax,1
rcl dx,1
rcl bl,1
;make a copy of 2X accumulator in BH:SI:DI
mov di,ax
mov si,dx
mov bh,bl
;multiply the copy by 2 (4X accumulator)
shl di,1
rcl si,1
rcl bh,1
;multiply the copy by 2 again (8X accumulator)
shl di,1
rcl si,1
rcl bh,1
;add the two together (8X + 2X = 10X)
add ax,di
adc dx,si
adc bl,bh
question - are these strings terminated with a null ?
Hi,
Google Groups search is working, So here is a posting
that I've used more or less. Look for Jonathan Kirwan's
post.
http://groups.google.com/group/comp.lang.asm.x86/browse_thread/thread/46b3636831e83c10/362f7cbd956fa882?hl=en&lnk=gst&q=jonathan+kirwan+128+print#362f7cbd956fa882
Regards,
Steve
ascii number can be terminated with a null in the new ascii to binary routine, doesn't matter to me which.
The ascii number passed to existing double word routine I use assumes a left-justified, 20h terminated ascii
number, but can easily be changed to expect null terminated instead, just trying to keep new 3 word routine
pass/return parameters as close as possible to my existing double word routines.
My current double word ascii to binary: pass [si] = buf addr of max 10-digit =< 4294967295, L J, blank terminated ascii number
returns ax/dx = (lsw/msw) binary value
My current double word binary to ascii: pass ax/dx = (lsw/msw) binary value
[di] = 10 byte destination buf
returns nothing (destination buf passed above is populated with ascii number)
well - you can use TEST AL,0DFh - that way, either a space or a null will detect the end
after my nap, i'll write up a little code for you
i need to stay in practice with 16-bit code - lol
Dedndave,
Thanks so much for your segment of code I used in my 'ascbin12' subroutine below to accomplish my
ascii to binary conversion of a 12 digit number into 3 words. I debugged it and it seems to be converting
large ascii strings to the correct binary values. I checked my program with several large numbers returning
register with > than double word values using asciii input numbers '999999999999' to '4500999999'
My only question is on the line where I put the '????' comment in the subroutiine, when adding the current
binary digit to my accumlative totals I'm keeping in ax/dx/bl:
add ax,cx ; these two lines are keeping total in ax,dx registers
adc dx,0
but that NEXT line: ' adc bl,0 ' I don't know if this is the correct way to take overflow from Dx register
and carry over to my Most Significant byte bl register once ax,dx are maxed out, (for example:) at some time at
this point in the code, say ax=0ffffh, dx=0fffeh and I'm adding a value in cx which = 6? Is this correct.
See code below.
Also, any ideas you want to share with me on the other routine I need to go from 3-word binary number input
and convert to a max 12 ascii digit '999999999999' output?
Thanks again - Dale
; <<<< var's declared in my .asm data segment >>>>
numb db '999999999999',20h ;asciii input number to convert to binary
digadr dw 0 ;var used to track address of each asciii digit
cnt12 db 0 ;digit counter var
; <<<<< my main routine in .asm code segment >>>>>>
.....
-----
lea si,numb ;pass addr of ascii number
call ascbin12 ;call ascii to binary routine below
;>> upon return here ax,dx/bl contain coverted binary value
.....
.....
;------------------------------------------------- sub-routine follows ----------------
public ascbin12 ;>> Convert ascii num =< '999999999999' to binary <<
ascbin12 proc near ; CALL: [si] = addr of L J ascii Max 12-digit buf, 20h-term'd buffer
;RETURNS: ax/dx/bx = binary number (bh always = 0)
mov digadr,si ;save off calling addr of ascii number buffer
sub ax,ax
mov dx,ax
mov bx,ax
mov cx,ax
mov cnt12,0 ;zero total #digits counter
nxdg2: mov si,digadr ;move to cl ascii digit from buf
mov cl,byte ptr [si]
inc digadr ;inc to next ascii digit in buf
and cl,0fH ;remove 30h to cvt digit to binary
add ax,cx ;add binary digit value to ax/dx/bl
adc dx,0
adc bl,0 ;????
inc cnt12 ;inc total #digit processed count
cmp cnt12,12 ;exit if processed max 12 digits
jz fn12
mov si,digadr
cmp byte ptr [si],20h ;exit if just processed/added last digit
jz fn12
;<< now multiply by 10
;multiply the accumulator by 2
shl ax,1
rcl dx,1
rcl bl,1
;make a copy of 2X accumulator in BH:SI:DI
mov di,ax
mov si,dx
mov bh,bl
;multiply the copy by 2 (4X accumulator)
shl di,1
rcl si,1
rcl bh,1
;multiply the copy by 2 again (8X accumulator)
shl di,1
rcl si,1
rcl bh,1
;add the two together (8X + 2X = 10X)
add ax,di
adc dx,si
adc bl,bh
jmp nxdg2 ;go get next ascii digit
fn12: mov bh,0 ;return binary value in ax/dx/bl (init bh=0 on exit so can save entire BX register contents)
ret
ascbin12 endp
;******************************************************
yes - that's right
you want a carry bit to "ripple" all the way through
although - you might want to make sure CH is also zero before the add
i didn't read all the way through to see if that is true
if not, change AND CL,0Fh to AND CX,0Fh and that will insure that CH is 0
if it is, then you can use....
add ax,cx
adc dx,0
adc bl,ch
it saves a clock cycle or 2 :bg
(CH is a 0)
there are a few other little things i would change
let me wake up and have a look :P
here you go, Dale
give this a try...
Thanks a lot dedndave, you were obviously a big help to me
on this little convertion routine. see ya later - Dale