-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathDF87.ASM
498 lines (458 loc) · 6.13 KB
/
DF87.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
; *******************************************************
; * *
; * Turbo Pascal Run-time Library *
; * 8087 Binary/Decimal Routines *
; * *
; * Copyright (c) 1988,92 Borland International *
; * *
; *******************************************************
TITLE DF87
INCLUDE SE.ASM
CODE SEGMENT BYTE PUBLIC
ASSUME CS:CODE
; Externals
EXTRN Str2Int:NEAR
; Publics
PUBLIC Float2Str,Str2Float
; Constants
DCon1E0 DD 1
DCon1E1 DD 10
DCon1E2 DD 100
DCon1E3 DD 1000
DCon1E4 DD 10000
DCon1E5 DD 100000
DCon1E6 DD 1000000
DCon1E7 DD 10000000
FCon1E8 DT 1E8
FCon1E16 DT 1E16
FCon1E32 DT 1E32
FCon1E64 DT 1E64
FCon1E128 DT 1E128
FCon1E256 DT 1E256
FCon1E512 DT 1E512
FCon1E1024 DT 1E1024
FCon1E2048 DT 1E2048
FCon1E4096 DT 1E4096
FCon1E18 DT 1E18
FConINF DT 07FFF8000000000000000R
; 8087 control word
CWNear DW 133FH
; Convert float to string
; In CX = Digit count (Float<0, Fixed>=0)
; ES:DI = String pointer
; ST(0) = Value
; Out CX = String length
; ES:DI = String pointer
Float2Str:
LOC CtrlWord,WORD,1
LOC StatWord,WORD,1
LOC Digits,WORD,1
LOC Exponent,WORD,1
LOC Sign,WORD,1
LOC Value,TBYTE,1
LOC DigitBuf,BYTE,20
ENTRY
FSTCW CtrlWord
FLDCW CWNear
FSTP Value
PUSH DI
CMP CX,18
JLE @@1
MOV CX,18
@@1: CMP CX,-18
JGE @@2
MOV CX,-18
@@2: MOV Digits,CX
CLD
FWAIT
MOV AX,Value.w8
MOV Sign,AX
AND AX,7FFFH
JE @@5
CMP AX,7FFFH
JNE @@10
CMP Value.w6,8000H
JE @@3
MOV AX,'AN'
STOSW
MOV AL,'N'
STOSB
JMP @@90
@@3: CMP Sign,0
JNS @@4
MOV AL,'-'
STOSB
@@4: MOV AX,'NI'
STOSW
MOV AL,'F'
STOSB
JMP @@90
@@5: MOV Exponent,AX
MOV DigitBuf,AL
JMP @@30
@@10: MOV Value.w8,AX
FLD Value
SUB AX,3FFFH
MOV DX,19728
IMUL DX
MOV Exponent,DX
MOV AX,17
SUB AX,DX
CALL Power10
FRNDINT
FLD FCon1E18
FCOMP
FSTSW StatWord
FWAIT
TEST StatWord,mC0+mC3
JE @@11
FIDIV DCon1E1
INC Exponent
@@11:
IF WindowsVersion
CMP BYTE PTR CS:@@12,0CDH
JNE @@12
PUSH ES
PUSH DI
LEA DI,DigitBuf
PUSH SS
POP ES
CALL FStoreBCD
POP DI
POP ES
JMP SHORT @@20
ENDIF
@@12: FBSTP Value
LEA BX,DigitBuf
MOV CL,4
MOV SI,9
FWAIT
@@13: MOV AL,Value[SI-1].b0
MOV AH,AL
SHR AL,CL
AND AH,0FH
ADD AX,'00'
MOV SS:[BX],AX
INC BX
INC BX
DEC SI
JNE @@13
MOV SS:[BX],SI
@@20: CMP Digits,0
JL @@21
CMP Exponent,36
JL @@21
MOV Digits,-18
@@21: MOV SI,Digits
OR SI,SI
JS @@22
ADD SI,Exponent
INC SI
JNS @@23
MOV DigitBuf,0
JMP SHORT @@30
@@22: NEG SI
@@23: CMP SI,18
JAE @@30
CMP DigitBuf[SI],'5'
MOV DigitBuf[SI],0
JB @@30
@@24: DEC SI
JS @@25
INC DigitBuf[SI]
CMP DigitBuf[SI],'9'
JBE @@30
MOV DigitBuf[SI],0
JMP SHORT @@24
@@25: MOV DigitBuf.w0,'1'
INC Exponent
@@30: XOR SI,SI
MOV DX,Digits
OR DX,DX
JS @@40
CMP Sign,0
JNS @@31
MOV AL,'-'
STOSB
@@31: MOV CX,Exponent
OR CX,CX
JNS @@32
MOV AL,'0'
STOSB
JMP SHORT @@33
@@32: CALL GetDigit
STOSB
DEC CX
JNS @@32
@@33: OR DX,DX
JE @@90
MOV AL,'.'
STOSB
@@34: INC CX
JE @@35
MOV AL,'0'
STOSB
DEC DX
JNE @@34
@@35: DEC DX
JS @@90
CALL GetDigit
STOSB
JMP SHORT @@35
@@40: MOV AL,' '
CMP Sign,0
JNS @@46
MOV AL,'-'
@@46: STOSB
CALL GetDigit
STOSB
INC DX
JE @@42
MOV AL,'.'
STOSB
@@41: CALL GetDigit
STOSB
INC DX
JNE @@41
@@42: MOV AL,'E'
STOSB
MOV AL,'+'
MOV DX,Exponent
OR DX,DX
JNS @@43
MOV AL,'-'
NEG DX
@@43: STOSB
MOV AX,(100*256)+10
XCHG AX,DX
DIV DH
MOV DH,AH
CBW
DIV DL
ADD AX,'00'
STOSW
MOV AL,DH
CBW
DIV DL
ADD AX,'00'
STOSW
@@90: MOV CX,DI
POP DI
SUB CX,DI
FCLEX
FLDCW CtrlWord
FWAIT
EXIT
; Get digit from digit buffer
GetDigit:
MOV AL,DigitBuf[SI]
INC SI
OR AL,AL
JNE @@1
MOV AL,'0'
DEC SI
@@1: RET
; Convert string to float
; In CX = String length
; ES:DI = String pointer
; Out CX = Remaining characters
; ES:DI = Pointer past string
; CF = 1 if error
; ST(0) = Value
Str2Float:
LOC CtrlWord,WORD,1
LOC TempWord,WORD,1
LOC SignChar,BYTE,1
LOC ExpoChar,BYTE,1
ENTRY
FSTCW CtrlWord
FCLEX
FLDCW CWNear
FLDZ
JCXZ @@7
MOV AL,ES:[DI]
MOV SignChar,AL
CMP AL,' '
JE @@1
CMP AL,'+'
JE @@1
CMP AL,'-'
JNE @@2
@@1: INC DI
DEC CX
@@2: PUSH CX
CALL DigitStr
XOR BX,BX
JCXZ @@3
MOV AL,ES:[DI]
CMP AL,'.'
JNE @@3
INC DI
DEC CX
CALL DigitStr
NEG BX
@@3: POP AX
CMP AX,CX
JE @@7
JCXZ @@5
MOV AL,ES:[DI]
CMP AL,'E'
JE @@4
CMP AL,'e'
JNE @@5
@@4: INC DI
DEC CX
PUSH BX
CALL Str2Int
POP BX
JC @@7
MOV SI,DX
CWD
CMP SI,DX
JNE @@7
CMP AX,4999
JGE @@7
CMP AX,-4999
JLE @@7
ADD BX,AX
@@5: MOV AX,BX
CALL Power10
CMP SignChar,'-'
JNE @@6
FCHS
@@6: FSTSW TempWord
FWAIT
TEST TempWord,mIE+mOE
JE @@8
@@7: STC
@@8: FCLEX
FLDCW CtrlWord
FWAIT
EXIT
; Process string of digits
; Out BX = Digit count
DigitStr:
XOR BX,BX
@@1: JCXZ @@2
MOV AL,ES:[DI]
SUB AL,'0'+10
ADD AL,10
JNC @@2
FIMUL DCon1E1
CBW
MOV TempWord,AX
FIADD TempWord
INC BX
INC DI
DEC CX
JMP @@1
@@2: RET
; Multiply ST(0) by 10^AX
; In AX = Power of 10
Power10:
CMP AX,4096
JLE @@1
FLD FCon1E4096
FMUL
SUB AX,4096
@@1: CMP AX,-4096
JGE @@2
FLD FCon1E4096
FDIV
ADD AX,4096
@@2: MOV BX,AX
OR AX,AX
JE @@8
JNS @@3
NEG AX
@@3: MOV SI,AX
AND SI,7
SHL SI,1
SHL SI,1
FILD DCon1E0[SI]
SHR AX,1
SHR AX,1
SHR AX,1
MOV SI,OFFSET FCon1E8
JMP SHORT @@6
@@4: SHR AX,1
JNC @@5
FLD TBYTE PTR CS:[SI]
FMUL
@@5: ADD SI,10
@@6: OR AX,AX
JNE @@4
OR BX,BX
JS @@7
FMUL
RET
@@7: FDIV
@@8: RET
IF WindowsVersion
; Store ST(0) as 18 decimal digits
; In ES:DI = Digit buffer pointer
FStoreBCD:
ADD DI,18
XOR AX,AX
STD
STOSW
SUB SP,8
MOV SI,SP
FISTP QWORD PTR SS:[SI]
FWAIT
POP BX
POP CX
POP AX
POP DX
MOV SI,10000
DIV SI ;CX:BX:AX = DX:AX:CX:BX div 10000
XCHG AX,CX
DIV SI
XCHG AX,BX
DIV SI
CALL StoreDigits
XOR DX,DX ;BX:CX:AX = CX:BX:AX div 10000
XCHG AX,CX
DIV SI
XCHG AX,BX
DIV SI
XCHG AX,CX
DIV SI
CALL StoreDigits
MOV DX,BX ;CX:AX = BX:CX:AX div 10000
XCHG AX,CX
DIV SI
XCHG AX,CX
DIV SI
CALL StoreDigits
MOV DX,CX ;AX = CX:AX div 10000
DIV SI
CALL StoreDigits
AAM
XCHG AL,AH
ADD AX,'00'
STOSW
CLD
RET
; Store four BCD digits
StoreDigits:
PUSH AX
MOV AL,100
XCHG AX,DX
DIV DL
MOV DL,AH
AAM
ADD AX,'00'
XCHG AL,AH
XCHG AX,DX
AAM
ADD AX,'00'
XCHG AL,AH
STOSW
XCHG AX,DX
STOSW
POP AX
RET
ENDIF
CODE ENDS
END