Subversion Repositories Kolibri OS

Rev

Rev 7128 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2165 IgorA 1
;
2
; функции для работы с числами float
3
;
4
 
5
; Количество знаков числа после запятой (1-17)
6
NumberSymbolsAD DW 5
7
; Константы (10 в степени N)
8
MConst DQ 1.0E1,1.0E2,1.0E3,1.0E4,1.0E5
9
       DQ 1.0E6,1.0E7,1.0E8,1.0E9,1.0E10
10
       DQ 1.0E11,1.0E12,1.0E13,1.0E14,1.0E15
11
       DQ 1.0E16,1.0E17,1.0E18,1.0E19,1.0E20
12
       DQ 1.0E21,1.0E22,1.0E23,1.0E24,1.0E25
13
       DQ 1.0E26,1.0E27,1.0E28,1.0E29,1.0E30
14
       DQ 1.0E31,1.0E32,1.0E33,1.0E34,1.0E35
15
       DQ 1.0E36,1.0E37,1.0E38,1.0E39,1.0E40
16
       DQ 1.0E41,1.0E42,1.0E43,1.0E44,1.0E45
17
       DQ 1.0E46,1.0E47,1.0E48,1.0E49,1.0E50
18
       DQ 1.0E51,1.0E52,1.0E53,1.0E54,1.0E55
19
       DQ 1.0E56,1.0E57,1.0E58,1.0E59,1.0E60
20
       DQ 1.0E61,1.0E62,1.0E63,1.0E64,1.0E65
21
       DQ 1.0E66,1.0E67,1.0E68,1.0E69,1.0E70
22
       DQ 1.0E71,1.0E72,1.0E73,1.0E74,1.0E75
23
       DQ 1.0E76,1.0E77,1.0E78,1.0E79,1.0E80
24
       DQ 1.0E81,1.0E82,1.0E83,1.0E84,1.0E85
25
       DQ 1.0E86,1.0E87,1.0E88,1.0E89,1.0E90
26
       DQ 1.0E91,1.0E92,1.0E93,1.0E94,1.0E95
27
       DQ 1.0E96,1.0E97,1.0E98,1.0E99,1.0E100
28
       DQ 1.0E101,1.0E102,1.0E103,1.0E104,1.0E105
29
       DQ 1.0E106,1.0E107,1.0E108,1.0E109,1.0E110
30
       DQ 1.0E111,1.0E112,1.0E113,1.0E114,1.0E115
31
       DQ 1.0E116,1.0E117,1.0E118,1.0E119,1.0E120
32
       DQ 1.0E121,1.0E122,1.0E123,1.0E124,1.0E125
33
       DQ 1.0E126,1.0E127,1.0E128
34
; Число с плавающей запятой двойной точности
35
Data_Double   DQ ?
36
; Число в BCD-формате
37
Data_BCD      DT ?
38
; Вспомогательный флаг
39
Data_Flag     DB ?
40
; Знак результата (если не 0 - отрицательное число)
41
Data_Sign     DB ?
7615 IgorA 42
; Знак результата - 0 для ..e+.. и 1 для ..e-..
43
Data_Sign_Exp DB ?
2165 IgorA 44
 
7615 IgorA 45
align 4
2165 IgorA 46
; Строка для хранения числа в коде ASCII
47
Data_String   DB 32 DUP (?)
48
 
49
 
50
 
51
;*******************************************************
52
;*  ПРЕОБРАЗОВАНИЕ ЧИСЛА С ПЛАВАЮЩЕЙ ЗАПЯТОЙ В СТРОКУ  *
53
;* Число имеет формат с удвоенной точностью, результат *
54
;* выдается в десятичном коде, в "бытовом" формате с   *
55
;* фиксированным количеством знаков после запятой.     *
56
;* Входные параметры:                                  *
57
;* Data_Double - преобразуемое число;                  *
58
;* NumberSymbolsAD - количество знаков после           *
59
;*                   запятой (0-17).                   *
60
;* Выходные параметры:                                 *
61
;* Data_String - строка-результат.                     *
62
;*******************************************************
7128 IgorA 63
align 4
2165 IgorA 64
DoubleFloat_to_String:
65
	pushad
66
	; Результат записывать в строку Data_String
67
	mov	EDI, Data_String
68
 
69
	; Сдвигаем число влево на NumberSymbolsAD
70
	; десятичных разрядов
71
	fninit		       ;сброс сопроцессора
72
	fld	[Data_Double]  ;загрузить число
73
	xor ebx,ebx
74
	mov	BX,[NumberSymbolsAD]
75
	cmp	BX, 0
76
	je	.NoShifts     ;нет цифр после запятой
77
	jl	.Error	      ;ошибка
78
	dec	BX
7615 IgorA 79
	lea ebx,[MConst+8*ebx]
2165 IgorA 80
	fmul	qword [EBX] ;умножить на константу
81
.NoShifts:
82
	; Извлечь число в коде BCD
83
	fbstp	[Data_BCD]
84
; Проверить результат на переполнение
85
	mov	AX,word [Data_BCD + 8]
86
	cmp	AX,0FFFFh  ;"десятичное" переполнение?
87
	je	.Overflow
88
; Выделить знак числа и записать его в ASCII-коде
89
	mov	AL, byte [Data_BCD + 9]
90
	and	AL,AL
91
	jz	.NoSign
92
	mov	AL,'-'
93
	stosb
94
.NoSign:
95
; Распаковать число в код ASCII
2254 IgorA 96
	mov	ebx,8	 ;смещение последней пары цифр
2165 IgorA 97
	mov	ecx,9	 ;счетчик пар цифр
98
	; Определить позицию десятичной точки в числе
99
	mov	DX,18
100
	sub	DX,[NumberSymbolsAD]
101
	js	.Error	;ошибка, если отрицательная
102
	jz	.Error	;или нулевая позиция
103
.NextPair:
104
	; Загрузить очередную пару разрядов
2254 IgorA 105
	mov	AL, byte [ebx + Data_BCD]
2165 IgorA 106
	mov	AH,AL
107
	; Выделить, перевести в ASCII и
108
	; сохранить старшую тетраду
109
	shr	AL,4
110
	add	AL,'0'
111
	stosb
112
	dec	DX
113
	jnz	.N0
114
	mov	AL,'.'
115
	stosb
116
.N0:   ; Выделить, перевести в ASCII и
117
	; сохранить младшую тетраду
118
	mov	AL,AH
119
	and	AL,0Fh
120
	add	AL,'0'
121
	stosb
122
	dec	DX
123
	jnz	.N1
124
	mov	AL,'.'
125
	stosb
126
.N1:
127
	dec  BX
128
	loop .NextPair
129
	mov  AL,0
130
	stosb
131
 
132
; Убрать незначащие нули слева
133
	mov	EDI, Data_String
134
	mov	ESI, Data_String
135
	; Пропустить знак числа, если он есть
136
	cmp	byte [ESI],'-'
137
	jne	.N2
138
	inc	ESI
139
	inc	EDI
140
.N2:   ; Загрузить в счетчик цикла количество разрядов
141
	; числа плюс 1 (байт десятичной точки)
142
	mov	ecx,18+1+1
143
	; Пропустить незначащие нули
144
.N3:
145
	cmp byte [ESI],'0'
146
	jne .N4
147
	cmp byte [ESI+1],'.'
148
	je .N4
149
	inc ESI
150
	loop .N3
151
	; Ошибка - нет значащих цифр
152
	jmp	.Error
153
; Скопировать значащую часть числа в начало строки
7128 IgorA 154
align 4
2165 IgorA 155
.N4:	rep movsb
156
	jmp    .End
157
; Ошибка
7128 IgorA 158
align 4
2165 IgorA 159
.Error:
160
	mov	AL,'E'
161
	stosb
162
	mov	AL,'R'
163
	stosb
164
	mov	AL,'R'
165
	stosb
166
	xor	AL,AL
167
	stosb
168
	jmp	.End
169
; Переполнение разрядной сетки
7128 IgorA 170
align 4
2165 IgorA 171
.Overflow:
172
	mov	AL,'#'
173
	stosb
174
	xor	AL,AL
175
	stosb
176
; Конец процедуры
7128 IgorA 177
align 4
2165 IgorA 178
.End:
179
	popad
180
	ret
181
 
182
;****************************************************
183
;* ПРЕОБРАЗОВАТЬ СТРОКУ В ЧИСЛО С ПЛАВАЮЩЕЙ ЗАПЯТОЙ *
184
;*      (число имеет обычный, "бытовой" формат)     *
185
;* Входные параметры:                               *
186
;* Data_String - число в коде ASCII.                *
187
;* Выходные параметры:                              *
188
;* Data_Double - число в двоичном коде.             *
189
;****************************************************
7128 IgorA 190
align 4
2165 IgorA 191
String_to_DoubleFloat:
192
	pushad
193
	cld
194
	; Очищаем Data_BCD
195
	mov dword [Data_BCD],0
196
	mov dword [Data_BCD+4],0
197
	mov  word [Data_BCD+8],0
198
	; Очищаем байт знака
199
	mov	[Data_Sign],0
7615 IgorA 200
	; Заносим в esi указатель на строку
201
	mov	esi, Data_String
2165 IgorA 202
	; Пропускаем пробелы перед числом
203
	mov	ecx,64 ;защита от зацикливания
204
.ShiftIgnore:
205
	lodsb
7615 IgorA 206
	cmp	al,' '
207
	jne .ShiftIgnoreEnd
208
	loop .ShiftIgnore
209
	jmp .Error
7128 IgorA 210
align 4
2165 IgorA 211
.ShiftIgnoreEnd:
212
	; Проверяем знак числа
7615 IgorA 213
	cmp	al,'-'
2165 IgorA 214
	jne	.Positive
215
	mov	[Data_Sign],80h
216
	lodsb
217
.Positive:
218
	mov	[Data_Flag],0 ;признак наличия точки
7615 IgorA 219
	xor	edx,edx	      ;позиция точки
2165 IgorA 220
	mov	ecx,18	      ;макс. число разрядов
7615 IgorA 221
align 4
2165 IgorA 222
.ASCIItoBCDConversion:
7615 IgorA 223
	cmp	al,'.'	      ;точка?
2165 IgorA 224
	jne	.NotDot
225
	cmp	[Data_Flag],0 ;точка не встречалась?
7615 IgorA 226
	jne	.Error        ;если точка уже была
2165 IgorA 227
	mov	[Data_Flag],1
228
	lodsb
7615 IgorA 229
	or al,al	      ;конец строки?
230
	jnz	.NotDot
2165 IgorA 231
	jmp	.ASCIItoBCDConversionEnd
7128 IgorA 232
align 4
2165 IgorA 233
.NotDot:
234
	; Увеличить на 1 значение позиции точки,
235
	; если она еще не встречалась
236
	cmp	[Data_Flag],0
237
	jnz	.Figures
7615 IgorA 238
	inc	edx
2165 IgorA 239
.Figures:
7615 IgorA 240
	cmp al,'e'
241
	je .exp_form
242
	cmp al,'E'
243
	jne @f
244
	.exp_form:
245
		call string_ExpForm ;если число в формате ..e..
246
		or al,al
247
		jnz .Error
248
		jmp	.ASCIItoBCDConversionEnd
249
	@@:
2165 IgorA 250
	; Символы числа должны быть цифрами
7615 IgorA 251
	cmp	al,'0'
2165 IgorA 252
	jb	.Error
7615 IgorA 253
	cmp	al,'9'
2165 IgorA 254
	ja	.Error
255
	; Пишем очередную цифру в младшую тетраду BCD
7615 IgorA 256
	and	al,15 ;символы 0-9 переводим в число
257
	or	byte [Data_BCD],al
2165 IgorA 258
	; Проверка на конец строки
7615 IgorA 259
	cmp	byte [esi],0
2165 IgorA 260
	je	.ASCIItoBCDConversionEnd
261
	; Сдвигаем BCD на 4 разряда влево
262
	; (сдвигаем старшие 2 байта)
7615 IgorA 263
	mov	ax,word [Data_BCD+6]
264
	shld	word [Data_BCD+8],ax,4
2165 IgorA 265
	; (сдвигаем средние 4 байта)
7615 IgorA 266
	mov	eax,dword [Data_BCD]
267
	shld	dword [Data_BCD+4],eax,4
2165 IgorA 268
	; (сдвигаем младшие 4 байта)
269
	shl	dword [Data_BCD],4
270
	; Загружаем следующий символ в AL
271
	lodsb
7615 IgorA 272
	loop .ASCIItoBCDConversion ;если не компил. то поставить dec ecx, jnz ...
2165 IgorA 273
	; Если 19-й символ не 0 и не точка,
274
	; то ошибка переполнения
7615 IgorA 275
	cmp	al,'.'
2165 IgorA 276
	jne	.NotDot2
7615 IgorA 277
	inc	ecx ;пропуск точки в конце очень большого числа
2165 IgorA 278
	lodsb
279
.NotDot2:
7615 IgorA 280
	or al,al	;переполнение разрядной сетки?
281
	jz	.ASCIItoBCDConversionEnd
282
align 4
283
.Error: ; При любой ошибке обнулить результат
284
	fldz	;занести ноль с стек сопроцессора
285
	fstp	[Data_Double]
286
	jmp	.End
2165 IgorA 287
 
288
; ПРЕОБРАЗОВАТЬ ЧИСЛО ИЗ КОДА BCD В ВЕЩЕСТВЕННОЕ ЧИСЛО
289
.ASCIItoBCDConversionEnd:
290
	; Вписать знак в старший байт
7615 IgorA 291
	mov	al,[Data_Sign]
292
	mov	byte [Data_BCD+9],al
2165 IgorA 293
	; Сбросить регистры сопроцессора
294
	fninit
295
	; Загрузить в сопроцессор число в BCD-формате
296
	fbld	[Data_BCD]
7615 IgorA 297
	; Вычислить номер делителя или множителя
298
	lea ebx,[ecx+edx-18]
299
	cmp ebx,0
300
	jle .NoMul ;если число e-..
301
	dec ebx
302
	jz .NoDiv ;если число e+0
303
	dec ebx
304
	lea ebx,[MConst+8*ebx]
305
	fmul qword [ebx] ;умножить на константу (для чисел с приставкой e+..)
306
	jmp .NoDiv
307
.NoMul:
308
	neg ebx
309
	lea ebx,[MConst+8*ebx]
310
	fdiv qword [ebx] ;разделить на константу
311
.NoDiv: ;Выгрузить число в двоичном формате
312
	fstp [Data_Double]
2165 IgorA 313
.End:
314
	popad
315
	ret
316
 
7615 IgorA 317
;output:
318
; eax - 1 if error
319
; edx += size
2165 IgorA 320
align 4
7615 IgorA 321
proc string_ExpForm uses ebx
322
	mov [Data_Sign_Exp],0
323
	xor eax,eax
324
	lodsb
325
	cmp al,'+'
326
	jne @f
327
		lodsb
328
	@@:
329
	cmp al,'-'
330
	jne @f
331
		inc [Data_Sign_Exp]
332
		lodsb
333
	@@:
334
 
335
	xor ebx,ebx
336
	.cycle0:
337
		cmp al,0
338
		je .cycle0end
339
		cmp al,9
340
		je .cycle0end
341
		cmp al,10
342
		je .cycle0end
343
		cmp al,13
344
		je .cycle0end
345
		cmp al,' '
346
		je .cycle0end
347
		cmp	al,'0'
348
		jb .Error
349
		cmp	al,'9'
350
		ja .Error
351
 
352
		imul ebx,10
353
		and	eax,15 ;символы 0-9 переводим в число
354
		add ebx,eax
355
		lodsb
356
		jmp .cycle0
357
	.cycle0end:
358
 
359
	cmp [Data_Sign_Exp],0
360
	je @f
361
		neg ebx
362
	@@:
363
	cmp	[Data_Flag],0 ;точка не встречалась?
364
	jne @f
365
		dec edx
366
	@@:
367
	add edx,ebx
368
 
369
	xor eax,eax
370
	jmp @f
371
	.Error:
372
		xor eax,eax
373
		inc eax
374
	@@:
375
	ret
376
endp
377
 
378
align 4
7128 IgorA 379
proc str_cat uses eax ecx edi esi, str1:dword, str2:dword
2165 IgorA 380
	mov esi,dword[str2]
381
	stdcall str_len,esi
382
	mov ecx,eax
383
	inc ecx
384
	mov edi,dword[str1]
385
	stdcall str_len,edi
386
	add edi,eax
387
	cld
388
	repne movsb
389
	ret
390
endp
391
 
392
;output:
393
; eax = strlen
394
align 4
395
proc str_len, str1:dword
396
	mov eax,[str1]
397
	@@:
398
		cmp byte[eax],0
399
		je @f
400
		inc eax
401
		jmp @b
402
	@@:
403
	sub eax,[str1]
404
	ret
7128 IgorA 405
endp
406
 
407
align 4
408
proc String_crop_0 uses eax ebx ecx edi
409
	mov edi,Data_String
410
	mov al,'.'
411
	mov ecx,32
412
	repne scasb
413
	mov ebx,edi
414
	mov edi,Data_String
415
	xor al,al
416
	mov ecx,32
417
	repne scasb
418
	cmp ebx,edi
419
	jg .end_f
420
	dec edi
421
	.cycle0:
422
		dec edi
423
		cmp edi,Data_String
424
		jle .end_f
425
		cmp byte[edi],'0'
426
		jne .cycle0end
427
		mov byte[edi],0
428
		jmp .cycle0
429
	.cycle0end:
430
	cmp byte[edi],'.'
431
	jne .end_f
432
		mov byte[edi],0
433
	.end_f:
434
	ret
2165 IgorA 435
endp