|
|
1.1 root 1: ////////
2: /
3: / Intel 8086 C runtime.
4: / Split a double into the fraction and whole integer parts.
5: / SMALL model.
6: /
7: ////////
8:
9: .globl modf_
10: .globl _fpac_
11: .globl dpush
12: .globl dladd
13: .globl dlsub
14: .globl dzero
15:
16: ////////
17: /
18: / double
19: / modf(d, *ip);
20: / double d;
21: / double *ip;
22: / The "integer part" of the double "d" is stored
23: / indirectly through "ip". The remaining fractional part
24: / is returned. The return value is always positive.
25: /
26: ////////
27:
28: d = 8 / Double argument
29: ip = 16 / Whole part pointer.
30:
31: EXP = -2 / Exponant.
32: SIGN = -4 / Sign flag.
33: CLAIM = 4 / # of bytes of autos.
34:
35: modf_: push si / Standard
36: push di / C
37: push bp / calling
38: mov bp,sp / sequence.
39:
40: sub sp,$CLAIM / Claim auto space
41: cld / Incrementing.
42:
43: lea si,d(bp) / Copy the "d" argument
44: mov di,ip(bp) / into the
45: movsw / integer return
46: movsw / value
47: movsw / output
48: movsw / area
49:
50: mov ax,d+6(bp) / Get the first word.
51: shl ax,$1 / Slide off the sign and
52: rclb SIGN(bp),$1 / save it.
53: movb al,ah / Save the exponant
54: subb ah,ah / in the ax,
55: sub ax,$0x80 / unbias it, and
56: mov EXP(bp),ax / save it away.
57:
58: / If the exponant is <= 0, then there is no
59: / integer part. Set the integer part to 0.0, and get set
60: / to return the argument as the fractional part.
61:
62: jg 0f / Jump if exponant > 0
63:
64: sub ax,ax / Set
65: mov di,ip(bp) / the
66: stosw / integer
67: stosw / part
68: stosw / to
69: stosw / zero.
70:
71: lea si,d(bp) / Copy
72: mov di,$_fpac_ / the
73: movsw / argument
74: movsw / to
75: movsw / the
76: movsw / return area.
77: jmp 1f / Done.
78:
79: / If the exponant is > 56 then there are no fractional bits
80: / at all. The integer part is correct. Zero out the floating point
81: / return value.
82:
83: 0: cmp ax,$56 / Any fractional bits ?
84: jl 0f / Yes.
85:
86: call dzero / Zero the _fpac_.
87: jmp 1f / Done.
88:
89: / Clear 56-exp bits, starting at the right hand end of the
90: / integer value. Clear as many full bytes as you can, then build a
91: / mask and get the rest.
92:
93: 0: neg ax / Figure out
94: add ax,$56 / 56-exp.
95: mov di,ip(bp) / Point di at low end.
96:
97: 0: sub ax,$8 / Is there a full byte ?
98: jl 0f / Nope.
99: movb (di),$0 / Clear 8 bits.
100: inc di / Move to next byte and
101: jmp 0b / try again.
102:
103: 0: add ax,$8 / Figure out
104: movb cl,al / the
105: movb al,$0xFF / correct mask to
106: shlb al,cl / clear the rest, and
107: andb (di),al / do it.
108:
109: / Scoop up the number. Shift the binary point to just above
110: / the hidden bit location, then shift it additional times to get
111: / it normalized.
112:
113: mov cx,EXP(bp) / Get exponant.
114:
115: movb dl,d+6(bp) / Scoop
116: mov ax,d+4(bp) / up
117: mov si,d+2(bp) / the
118: mov di,d+0(bp) / number.
119:
120: 0: shl di,$1 / Slide
121: rcl si,$1 / up
122: rcl ax,$1 / one
123: rclb dl,$1 / bit, and
124: loop 0b / loop until done.
125:
126: mov cx,di / Check
127: or cx,si / if
128: or cx,ax / we
129: orb cl,dl / have a zero.
130: jnz 0f / Nope.
131: subb dh,dh / Make all zeros and
132: jmp 2f / return.
133:
134: 0: mov cx,$0x8000 / ch=exp, cl=0
135:
136: 0: orb dl,dl / Normalized ?
137: js 0f / Yes.
138: shl di,$1 / Shift
139: rcl si,$1 / up
140: rcl ax,$1 / one
141: rclb dl,$1 / place.
142: decb ch / Adjust exponant and
143: jmp 0b / loop.
144:
145: 0: and dx,$0x7F / dh=0, dl=no hidden bit
146: shrb SIGN(bp),$1 / carry=sign
147: rcr cx,$1 / Pull into correct place and
148: or dx,cx / pack up double.
149:
150: 2: mov _fpac_+6,dx / Save
151: mov _fpac_+4,ax / into the
152: mov _fpac_+2,si / return
153: mov _fpac_+0,di / location.
154:
155: 1: mov sp,bp / Standard
156: pop bp / C
157: pop di / function
158: pop si / return
159: ret / code.
160:
161: .shrd
162: one: .byte 0x00, 0x00, 0x00, 0x00
163: .byte 0x00, 0x00, 0x80, 0x40
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.