Annotation of coherent/b/lib/libc/gen/i8086/atof.s, revision 1.1.1.1

1.1       root        1: ////////
                      2: /
                      3: / Intel 8086 C runtime.
                      4: / convert ascii string to double binary.
                      5: / small model.
                      6: /
                      7: ////////
                      8: 
                      9:        .globl  atof_
                     10:        .globl  _fpac_
                     11: 
                     12: ////////
                     13: /
                     14: / ** atof_ -- convert ascii string to double binary.
                     15: /
                     16: / this routine converts a floating point number from ascii into double
                     17: / precision floating point binary. it is c callable. conversion  stops
                     18: / on the first illegal character. there is no error status passed back
                     19: / for bad numbers or over/underflows. this version of atof does decvax
                     20: / floating point; it can be changed to do ieee trivially (look at  the
                     21: / conversion routine in n0/lex.c to see how to do this).
                     22: /
                     23: / calling sequence:
                     24: /      double  atof();
                     25: /      double  d;
                     26: /      char    *p;
                     27: /      d = atof(p);
                     28: /
                     29: / outputs:
                     30: /      _fpac_=result.
                     31: /
                     32: / uses:
                     33: /      ax, bx, cx, dx
                     34: /
                     35: ////////
                     36: 
                     37: string =       8                       / the string argument
                     38: binexp =       -2                      / binary exponant
                     39: decexp =       -4                      / decimal exponant (byte)
                     40: flags  =       -3                      / flags (byte)
                     41: fldexp =       -4                      / for clearing flags/decexp
                     42: num    =       -12                     / a scratch double.
                     43: 
                     44: claim  =       12                      / number of bytes of autos.
                     45: negnum =       0x01                    / negative number (must be 01)
                     46: negexp =       0x02                    / negative exponant
                     47: gotdot =       0x04                    / got dot flag
                     48: 
                     49: ten:   .byte   10                      / a 10 in the code segment.
                     50: 
                     51: atof_: push    si                      / standard
                     52:        push    di                      / c
                     53:        push    bp                      / function
                     54:        mov     bp,sp                   / linkage
                     55: 
                     56:        sub     sp,$claim               / get space for autos
                     57:        cld                             / make lodsb increment si.
                     58: 
                     59:        sub     cx,cx                   / zero out the
                     60:        mov     bx,cx                   / big register used to
                     61:        mov     di,cx                   / hold doubles
                     62:        mov     dx,cx                   / during conversion (dx,di,bx,cx)
                     63:        mov     fldexp(bp),cx           / clear flags, decexp
                     64:        mov     binexp(bp),$65+128      / initialise binary exponant
                     65: 
                     66:        mov     si,string(bp)           / get string argument.
                     67: 
                     68: l0:    lodsb                           / al=character.
                     69:        cmpb    al,$040                 / is it a space?
                     70:        je      l0                      / loop on white space
                     71:        cmpb    al,$011                 / is it a tab?
                     72:        je      l0                      / loop on white space
                     73: 
                     74:        cmpb    al,$'+                  / plus sign ??
                     75:        je      l1                      / yes, eat it up.
                     76:        cmpb    al,$'-                  / minus sign ??
                     77:        jne     l2                      / no, go get number.
                     78:        incb    flags(bp)               / set "negnum" flag.
                     79: 
                     80: l1:    lodsb                           / al=character.
                     81: 
                     82: l2:    cmpb    al,$'.                  / decimal point character ??
                     83:        jne     l3                      / jump if not.
                     84:        testb   flags(bp),$gotdot       / have we seen a dot ??
                     85:        jnz     l12                     / yes, quit.
                     86:        orb     flags(bp),$gotdot       / we have seen one now.
                     87:        jmp     l1                      / go on.
                     88: 
                     89: l3:    subb    al,$'0                  / remove ascii bias.
                     90:        cmpb    al,$9                   / legal digit ??
                     91:        ja      l6                      / no (ja makes < '0' look huge)
                     92:        testb   dh,$0xF8                / do we have 5 bits ??
                     93:        jz      l4                      / yes.
                     94:        incb    decexp(bp)              / nope, toss significance.
                     95:        jmp     l5                      / done with this digit.
                     96: 
                     97: l4:    call    shlreg                  / multiply
                     98:        call    storeg                  / the big
                     99:        call    shlreg                  / register
                    100:        call    shlreg                  / by
                    101:        call    addreg                  / 10 (8+2 = 10).
                    102:        cbw                             / ax = new digit.
                    103:        add     cx,ax                   / add into the low word.
                    104:        call    ripple                  / ripple carries.
                    105: 
                    106: l5:    testb   flags(bp),$gotdot       / are we after the "." ??
                    107:        jz      l1                      / jump if not.
                    108:        decb    decexp(bp)              / yes, adjust scale.
                    109:        jmp     l1                      / go get another digit.
                    110: 
                    111: l6:    cmpb    al,$'e-'0               / exponant ??
                    112:        jz      l7                      / yes.
                    113:        cmpb    al,$'E-'0               / perhaps ??
                    114:        jnz     l12                     / nope, all done.
                    115: 
                    116: l7:    push    dx                      / get a work register.
                    117:        subb    dh,dh                   / dh=exponant.
                    118:        lodsb                           / al=character.
                    119:        cmpb    al,$'+                  / positive ??
                    120:        je      l8                      / yes, eat it up.
                    121:        cmpb    al,$'-                  / negative ??
                    122:        jne     l9                      / nope, its first character.
                    123:        orb     flags(bp),$negexp       / set flag.
                    124: 
                    125: l8:    lodsb                           / al=character.
                    126: 
                    127: l9:    subb    al,$'0                  / remove any ascii bias.
                    128:        cmpb    al,$9                   / legal ??
                    129:        ja      l10                     / nope, all done.
                    130:        xchgb   dh,al                   / al=old exponant, dh=digit.
                    131:        mulb    cs:ten                  / old=10*old.
                    132:        addb    dh,al                   / exp=10*old+digit
                    133:        jmp     l8                      / loop until the end of exp.
                    134: 
                    135: l10:   testb   flags(bp),$negexp       / was the exponant lt 0 ??
                    136:        jz      l11                     / nope.
                    137:        negb    dh                      / fix it up.
                    138: 
                    139: l11:   addb    decexp(bp),dh           / fix up decimal exponant.
                    140:        pop     dx                      / recover work register.
                    141: 
                    142: l12:   mov     ax,di                   / quick
                    143:        or      ax,bx                   / check
                    144:        or      ax,cx                   / for
                    145:        or      ax,dx                   / zero.
                    146:        jnz     l13                     / jump if non zero.
                    147:        jmp     l25                     / zero is easy.
                    148: 
                    149: l13:   movb    al,decexp(bp)           / al=decimal exponant.
                    150:        orb     al,al                   / check its sign.
                    151:        jle     l18                     / jump if not multiply scaling.
                    152: 
                    153: l14:   call    storeg                  / save big reg in "num".
                    154:        call    shlreg                  / can it take a * 5 ??
                    155:        jc      l15                     / nope
                    156:        call    shlreg                  / well ??
                    157:        jc      l15                     / nope
                    158:        call    addreg                  / last try ??
                    159:        jc      l15                     / nope
                    160:        inc     binexp(bp)              / yes, 5*2 = 10
                    161:        jmp     l17                     / go test if all done.
                    162: 
                    163: l15:   call    lodreg                  / fetch number.
                    164:        call    shrreg                  / figure out
                    165:        call    shrreg                  / 5/4 of the old
                    166:        call    addreg                  / number.
                    167:        jnc     l16                     / harumph, overflow.
                    168:        call    rcrreg                  / easily
                    169:        inc     binexp(bp)              / repaired, though.
                    170: 
                    171: l16:   add     binexp(bp),$3           / 5/4 * 8 = 10
                    172: 
                    173: l17:   decb    decexp(bp)              / are we done ??
                    174:        jnz     l14                     / nope
                    175:        jmp     l23                     / yup
                    176: 
                    177: l18:   jz      l23                     / jump if no scaling
                    178: 
                    179: l19:   or      dx,dx                   / first
                    180:        js      l20                     / we
                    181:        call    shlreg                  / left
                    182:        dec     binexp(bp)              / justify the
                    183:        jmp     l19                     / fraction.
                    184: 
                    185: l20:   call    shrreg                  / position number
                    186:        call    storeg                  / get it in
                    187:        movb    al,$32                  / al=step counter.
                    188: 
                    189: l21:   testb   al,$0x01                / odd iteration ??
                    190:        jz      l22                     / nope.
                    191:        call    shrreg                  / yes, 4/5 = 0.110011001100
                    192:        call    shrreg                  / so do two extra shifts.
                    193: 
                    194: l22:   call    shrreg                  / shift over and
                    195:        add     num+0(bp),cx            / add it
                    196:        adc     num+2(bp),bx            / into
                    197:        adc     num+4(bp),di            / the
                    198:        adc     num+6(bp),dx            / number.
                    199:        decb    al                      / any more loops ??
                    200:        jnz     l21                     / yes.
                    201: 
                    202:        call    lodreg                  / result in
                    203:        sub     binexp(bp),$3           / 1/10 = 4/5 * 1/8
                    204:        incb    decexp(bp)              / done ??
                    205:        jnz     l19                     / jump if not.
                    206: 
                    207: l23:   dec     binexp(bp)              / shift left until
                    208:        call    shlreg                  / the hidden bit
                    209:        jnc     l23                     / appears.
                    210:        addb    ch,$1                   / round just below
                    211:        call    ripple                  / the last bit we keep.
                    212:        jnc     l24                     / no carry on rounding.
                    213:        call    shrreg                  / carry flips hidden bit and
                    214:        inc     binexp(bp)              / fix exponant.
                    215: 
                    216: l24:   movb    al,$8                   / al=step counter.
                    217: l24a:  call    shrreg                  / slide the number down
                    218:        decb    al                      / to make room for
                    219:        jnz     l24a                    / the exponant.
                    220:        movb    dh,binexp(bp)           / get binary exponant.
                    221:        rcrb    flags(bp),$1            / sign in c.
                    222:        call    rcrreg                  / finish up the number.
                    223: 
                    224: l25:   mov     _fpac_+6,dx             / store
                    225:        mov     _fpac_+4,di             / the
                    226:        mov     _fpac_+2,bx             / big
                    227:        mov     _fpac_+0,cx             / number
                    228: 
                    229:        mov     sp,bp                   / do
                    230:        pop     bp                      / standard
                    231:        pop     di                      / c
                    232:        pop     si                      / function
                    233:        ret                             / return.
                    234: 
                    235: ////////
                    236: /
                    237: / ** shrreg -- shift big register right.
                    238: / ** rcrreg -- shift big register right, using carry.
                    239: /
                    240: ////////
                    241: 
                    242: shrreg:        shr     dx,$1                   / do first word and
                    243:        jmp     l30                     / finish up in common code.
                    244: 
                    245: rcrreg:        rcr     dx,$1                   / do first word.
                    246: 
                    247: l30:   rcr     di,$1                   / shift down the
                    248:        rcr     bx,$1                   / other three
                    249:        rcr     cx,$1                   / words and
                    250:        ret                             / return
                    251: 
                    252: ////////
                    253: /
                    254: / ** lodreg -- load big register from "num"
                    255: /
                    256: ////////
                    257: 
                    258: lodreg:        mov     dx,num+6(bp)            / load
                    259:        mov     di,num+4(bp)            / the
                    260:        mov     bx,num+2(bp)            / big
                    261:        mov     cx,num+0(bp)            / register and
                    262:        ret                             / return
                    263: 
                    264: ////////
                    265: /
                    266: / ** storeg -- store big register into "num"
                    267: /
                    268: ////////
                    269: 
                    270: storeg:        mov     num+6(bp),dx            / store
                    271:        mov     num+4(bp),di            / the
                    272:        mov     num+2(bp),bx            / big
                    273:        mov     num+0(bp),cx            / register and
                    274:        ret                             / return
                    275: 
                    276: ////////
                    277: /
                    278: / ** addreg -- add "num" to big register.
                    279: /
                    280: ////////
                    281: 
                    282: addreg:        add     cx,num+0(bp)            / add the
                    283:        adc     bx,num+2(bp)            / big register to
                    284:        adc     di,num+4(bp)            / the
                    285:        adc     dx,num+6(bp)            / number and
                    286:        ret                             / return
                    287: 
                    288: ////////
                    289: /
                    290: / ** ripple -- ripple c bit into register
                    291: /
                    292: ////////
                    293: 
                    294: ripple:        adc     bx,$0                   / ripple 
                    295:        adc     di,$0                   / carry
                    296:        adc     dx,$0                   / bits and
                    297:        ret                             / return
                    298: 
                    299: ////////
                    300: /
                    301: / ** shlreg -- shift big register left
                    302: /
                    303: ////////
                    304: 
                    305: shlreg:        shl     cx,$1                   / shift
                    306:        rcl     bx,$1                   / big
                    307:        rcl     di,$1                   / register
                    308:        rcl     dx,$1                   / left and
                    309:        ret                             / return

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.