;  codeasb.asm   converts an ASCII numeric string to a double word
;                binary equivalent
;
;  Inputs:    SI  points to the string that is to be converted. It is edited
;                 to ensure it is valid data.
;             CX  has the count of ASCII characters which may exceed the
;                 count of digits.
;  Process:   The procedure scans the string to get the count of digits. It
;             fetches decimal digit pairs from left to right. The prior
;             result is multiplied by 100, the new pair is converted to binary
;             and added to the prior result. Each pair in the source is
;             processed. (If an odd # of digits are presented, the first digit
;             is processed alone.)
;  Output:    If the conversion is without overflow, carry is reset and EAX
;             contains the result.
;             If the conversion overflows, carry is set and EAX is undefined.
;             If no digits are valid, the result is zero in EAX.
;             SI points to the digit following the last character converted
;             and CX contains the remaining count.
;
.model       small
.386

public codeasb

.code

codeasb      proc
             push         ebx
             push         edx
             push         di
             push         si                ; save first character pointer
             sub          ebx,ebx           ; clear the result
             sub          eax,eax           ; and the rest of eax.
             cld                            ; force direction to up
             cmp          byte ptr[si],'-'  ; negative ?
             je           signed            ; yes
             cmp          byte ptr[si],'+'  ; positive
             jne          unsigned          ; no, skip
signed:
             inc          si                ; step over of sign
             dec          cx                ; and counting it
unsigned:
             push         si                ; save for conversion pass
             mov          di,cx             ; save char count
             mov          dx,0930h          ; set '0' in dl and 9 in dh
             jcxz         numdone
numscan:
             lodsb                          ; get a possible digit
             xor          al,dl
             cmp          al,dh             ; check if it is a digit
             ja           numdone
             loop         numscan
numdone:
             pop          si                ; restore for conversion pass
             xchg         cx,di             ; set original count
             sub          cx,di             ; and get digit count
             test         cl,1              ; is the count odd ?
             jz           cxeven            ; no, skip
             lodsb                          ; the load of the first byte
             and          al,15             ; as a binary value.
             mov          bl,al             ; we have a starting value
cxeven:
             shr          cx,1              ; divide the count by 2
             jz           outgood           ; if the result is zero - out
             push         ebp
             mov          ebp,100           ; get multiplier in a register
dopair:
             lodsw                          ; get pair of bytes(reversed)
             xchg         al,ah             ; back in proper order
             and          ax,0f0fh          ; clear zones
             aad                            ; convert pair to binary
             xchg         eax,ebx           ; position accum for mpy
             mul          ebp               ; and make room for digits
             or           edx,edx           ; check for overflow
             jnz          outoflo           ; out if it did
             or           eax,eax           ; check overflow into sign
             js           outoflo           ; out if it did
             add          eax,ebx           ; add new pair in
             jo           outoflo           ; exit if overflow occured
             xchg         eax,ebx           ; put registers back
             loop         dopair            ; do each pair
             pop          ebp               ; restore ebp
outgood:                                    ; go back
             mov          eax,ebx           ; with number in eax
             mov          cx,di             ; remaining count in cx
             pop          bx                ; restore the sign pointer
             cmp          byte ptr [bx],'-' ; was a minus entered ?
             jne          positive          ; nope
             neg          eax               ; force it minus
positive:
             clc                            ; clear carry(neg could set)
             pop          di                ; restore the entry registers
             pop          edx               ;
             pop          ebx               ;
             ret                            ;
outoflo:
             pop          ebp               ; restore the work registers
             stc                            ; set error then
             pop          di                ; clear sign pointer
             pop          di                ; restore the entry registers
             pop          edx               ;
             pop          ebx               ;
             ret
codeasb      endp
end

