DOS-debug

Форк
0
/
FPTOSTR.INC 
412 строк · 7.3 Кб
1

2
;--- defines procedures
3
;--- PowerOf10
4
;--- FloatToBCD
5
;--- FloatToStr
6

7
; These are bits in the FP status word.
8

9
FP_LESSTHAN	equ 01h
10
FP_EQUALTO	equ 40h
11

12
MAXNUM equ 16
13

14
CONST segment
15

16
;ten	dq 10.0
17
;ten16	dq 1.0e16
18
;rounder	dq 5.0e10
19

20
iexp = 1
21

22
ten_1 label tbyte
23
repeat 15
24
	dt @CatStr(1.0e,%iexp)
25
	iexp = iexp + 1
26
endm
27

28
ten_16 label tbyte
29
repeat 15
30
	dt @CatStr(1.0e,%iexp)
31
	iexp = iexp + 16
32
endm
33

34
;--- just the first exponent is necessary for 8-byte doubles
35

36
ten_256 label tbyte
37
repeat 19
38
	dt @CatStr(1.0e,%iexp)
39
	iexp = iexp + 256
40
endm
41

42
CONST ends
43

44
;--- called by FloatToStr
45
;--- in: ax=exponent
46
;--- modifies: bx, cl
47

48
PowerOf10 proc uses si
49

50
	push ax
51
	cmp ax, 0		;.IF (SWORD PTR ax < 0)
52
	jge @F
53
	neg ax
54
@@:
55
	fld1
56
	mov bl, al
57
	and bl, 0fh		;bits 0-3
58
	je @F
59
	mov si,offset ten_1
60
	call mul10
61
@@:
62
	mov bl, al
63
	mov cl, 4
64
	shr bl, cl		;bits 4-7
65
;	and bl, 0fh
66
	je @F
67
	mov si,offset ten_16
68
	call mul10
69
@@:
70
	mov bl, ah
71
	and bl, 1fh		;bits 8-12
72
	je @F
73
	mov si,offset ten_256
74
	call mul10
75
@@:
76
	pop ax
77
	cmp ax, 0		;.IF (SWORD PTR ax < 0)
78
	jge @F
79
	fdivp st(1), st
80
	ret
81
@@:
82
	fmulp st(1), st
83
	ret
84
mul10:
85
	dec bl
86
	push ax
87
	mov al,10		; sizeof TBYTE
88
	mul bl
89
	xchg bx,ax
90
	pop ax
91
	fld tbyte ptr [bx + si]
92
	fmulp st(1), st
93
	retn
94

95
PowerOf10 ENDP
96

97
; Convert a floating point register to ASCII.  For internal use.
98
; The result always has exactly 18 digits, with zero padding on the
99
; left if required.
100
;
101
; Entry: ST(0) = a number to convert, 0 <= ST(0) < 1E19.
102
;        DI = an 18-character buffer.
103
; modifies SI,DI,CX,AX
104

105
FloatToBCD PROC
106

107
if FLATSS
108
	sub esp, 12
109
	mov esi, esp
110
else
111
	sub sp, 12
112
	mov si, sp
113
endif
114

115
	; The fbstp instruction converts the top of the stack to a
116
	; packed BCD form in ten bytes, with two digits per byte.  The top 
117
	; byte has the sign, which we ignore.
118

119
if FLATSS
120
	fbstp [esp]
121
else
122
	fbstp [si]
123
endif
124

125
	; Now we need to unpack the BCD to ASCII.
126

127
if FLATSS
128
	add esi, 8
129
else
130
	add si, 8
131
endif
132
	mov cx, 9
133
@@:
134
if FLATSS
135
	mov al, ss:[esi]	; xxxx xxxx AAAA BBBB
136
	dec esi
137
else
138
	mov al, [si]		; xxxx xxxx AAAA BBBB
139
	dec si
140
endif
141
if 0
142
	rol ax, 12			; BBBB xxxx xxxx AAAA
143
	rol ah, 4			; xxxx BBBB xxxx AAAA
144
	and ax, 0f0fh		; 0000 BBBB 0000 AAAA
145
else
146
	db 0D4h,10h			; aam 16: 0000 AAAA 0000 BBBB
147
	xchg al,ah			; 0000 BBBB 0000 AAAA
148
endif
149
	add ax, 3030h
150
	stosw
151
	loop @B
152
if FLATSS
153
	add esp, 12
154
else
155
	add sp, 12
156
endif
157
	ret
158

159
FloatToBCD ENDP
160

161
;
162
; Convert a double precision number to a string.
163
;
164
; Entry:   SI=fpin   = 10-byte double to convert
165
;          DI=pszDbl = buffer to hold converted double
166
;
167
; Exit:    DI = behind converted double
168

169
FloatToStr PROC USES si
170

171
if FLATSS
172
_DATA segment
173
iExp dw 0
174
;mystat dw 0
175
;szTemp db 22 dup (0)
176
_DATA ends
177
else
178
LOCAL iExp: WORD
179
LOCAL mystat: WORD
180
;local szTemp[22]:BYTE
181
endif
182

183
;--- Special case zero has been filtered already (fxtract fails for zero).
184

185
;--- Check for a negative number.
186

187
	mov cl,[si+9]
188
	test cl, 80h
189
	jz @F
190
	and byte ptr [si+9], 07fh		; change to positive
191
	mov al,'-'						; store a minus sign
192
	stosb
193
@@:
194

195
;--- load our value onto the stack.
196

197
	fld tbyte ptr [si]
198
	fld st
199
	mov [si+9], cl	; restore fpin, must be preserved.
200

201
; Compute the closest power of 10 below the number.  We can't get an
202
; exact value because of rounding.  We could get close by adding in
203
; log10(mantissa), but it still wouldn't be exact.  Since we'll have to
204
; check the result anyway, it's silly to waste cycles worrying about
205
; the mantissa.
206
;
207
; The exponent is basically log2(fpin).  Those of you who remember
208
; algebra realize that log2(fpin) x log10(2) = log10(fpin), which is
209
; what we want.
210

211
	fxtract			; ST=> mantissa, exponent, fpin
212
	fstp st			; drop the mantissa
213
	fldlg2			; push log10(2)
214
	fmulp st(1), st	; ST = log10(fpin), fpin
215
	fistp iExp		; ST = fpin
216

217
;--- A 10-byte double can carry almost 19 digits, but fbstp only stores the
218
;--- guaranteed 18.  If you're doing 10-byte doubles, change the '16' to '18'.
219

220
	cmp iExp, 18
221
	jnc notbelow18
222
    
223
	fld st			; ST = fpin, fpin
224
	frndint			; ST = int(fpin), fpin
225
	fcomp st(1)		; ST = fpin, status set
226
if RING0
227
	fstsw ax
228
else
229
	fstsw mystat
230
	mov ax, mystat
231
endif
232
	test ah, FP_EQUALTO
233
	jz notequal
234

235
;--- We have an integer!  Lucky day.  Go convert it into a temp buffer.
236

237
	push di
238
;	lea di, szTemp
239
	call FloatToBCD
240
	pop di
241

242
	mov ax, MAXNUM+1
243
	mov cx, iExp
244
	sub ax, cx
245
	inc cx
246
;	lea si, szTemp
247
	mov si, di
248
	add si, ax
249

250
;--- The off-by-one order of magnitude problem below can hit us here.  
251
;--- We just trim off the possible leading zero.
252

253
	cmp byte ptr [si],'0'
254
	jnz @F
255
	inc si
256
	dec cx
257
@@:
258

259
;--- Copy the rest of the converted BCD value to our buffer.
260

261
	rep movsb
262
	jmp ftsExit
263

264
notequal:
265
notbelow18:
266

267
;--- Have fbstp round to 17 places.
268

269
	mov ax, MAXNUM
270
	sub ax, iExp		; adjust exponent to 17
271
	call PowerOf10
272

273
; Either we have exactly 17 digits, or we have exactly 16 digits.  We can
274
; detect that condition and adjust now.
275

276
	fcom qword ptr [ten_16]
277
    ; x0xxxx00 means top of stack > ten16
278
    ; x0xxxx01 means top of stack < ten16
279
    ; x1xxxx00 means top of stack = ten16
280
if RING0
281
	fstsw ax
282
else
283
	fstsw mystat
284
	mov ax, mystat
285
endif
286
	test ah,1
287
	jz @F
288
	fmul qword ptr [ten_1]
289
	dec iExp
290
@@:
291

292
;--- Go convert to BCD.
293

294
	push di
295
	lea  di, [di+8]
296
	call FloatToBCD
297
	pop di
298

299
;	lea si, [szTemp+1]		; point to converted buffer
300
	lea si, [di+8+1]		; point to converted buffer
301

302
;--- If the exponent is between -15 and 16, we should express this as a number
303
;--- without scientific notation.
304

305
	mov cx, [iExp]
306
	push cx
307
	add cx,MAXNUM-1
308
	cmp cx,MAXNUM*2-1
309
	pop cx
310
	ja fts6		;if scientific notation
311

312
; If the exponent is less than zero, we insert '0.', then -ecx
313
; leading zeros, then 16 digits of mantissa.  If the exponent is
314
; positive, we copy ecx+1 digits, then a decimal point (maybe), then 
315
; the remaining 16-ecx digits.
316

317
	inc cx
318
	cmp cx, 0
319
	jg @F
320
	mov ax,'.0'
321
	stosw
322
	neg cx
323
	mov al, '0'
324
	rep stosb
325
	mov cx, MAXNUM
326
	jmp fts3
327
@@:
328
	rep movsb
329
	mov al,'.'
330
	stosb
331
	mov cx, MAXNUM
332
	sub cx, [iExp]
333
fts3:
334
	rep movsb
335

336
;--- Trim off trailing zeros.
337

338
@@:
339
	cmp byte ptr [di-1],'0'
340
	jnz @F
341
	dec di
342
	jmp @B
343
@@:
344

345
;--- If we cleared out all the decimal digits, kill the decimal point, too.
346

347
	cmp byte ptr [di-1], '.'
348
	jnz @F
349
	dec di
350
@@:    
351

352
;--- That's it.
353

354
	jmp ftsExit
355
fts6:
356
; Now convert this to a standard, usable format.  If needed, a minus
357
; sign is already present in the outgoing buffer, and di already points
358
; past it.
359

360
	movsb				; copy the first digit
361
	mov al,'.'
362
	stosb				; plop in a decimal point
363
	movsw				; copy four more digits
364
	movsw
365
	movsw				; copy two more digits
366

367
if 0
368

369
; The printf %g specified trims off trailing zeros here.  I dislike
370
; this, so I've disabled it.  Comment out the if 0 and endif if you
371
; want this.
372

373
@@:
374
	cmp byte ptr [di-1],'0'
375
	jz @F
376
	dec di
377
	jmp @B
378
@@:
379
endif
380

381
;--- Shove in the exponent.  If you support 10-byte reals, remember to
382
;--- allow 4 digits for the exponent.
383

384
	mov ax,'+e'
385
	mov dx, [iExp]
386
	and dx, dx
387
	jns @F
388
	neg dx
389
	mov ah,'-'
390
@@:
391
	stosw
392

393
	xchg ax,dx
394
	mov si, 10
395
	mov cx,4
396
@@:
397
	xor dx, dx
398
	div si
399
	push dx
400
	loop @B
401
	mov cl,4
402
@@:
403
	pop ax
404
	add al,'0'
405
	stosb
406
	loop @B
407

408
;	add di, 4	; point to terminator
409

410
ftsExit:
411
	ret
412

413
FloatToStr ENDP
414

415

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.