|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.