Subversion Repositories Kolibri OS

Rev

Rev 2254 | Rev 7615 | 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 ?
42
 
43
 
44
db 0 ;указатель на сдвиг в памяти
45
; Строка для хранения числа в коде ASCII
46
Data_String   DB 32 DUP (?)
47
 
48
 
49
 
50
;*******************************************************
51
;*  ПРЕОБРАЗОВАНИЕ ЧИСЛА С ПЛАВАЮЩЕЙ ЗАПЯТОЙ В СТРОКУ  *
52
;* Число имеет формат с удвоенной точностью, результат *
53
;* выдается в десятичном коде, в "бытовом" формате с   *
54
;* фиксированным количеством знаков после запятой.     *
55
;* Входные параметры:                                  *
56
;* Data_Double - преобразуемое число;                  *
57
;* NumberSymbolsAD - количество знаков после           *
58
;*                   запятой (0-17).                   *
59
;* Выходные параметры:                                 *
60
;* Data_String - строка-результат.                     *
61
;*******************************************************
7128 IgorA 62
align 4
2165 IgorA 63
DoubleFloat_to_String:
64
	pushad
65
	; Результат записывать в строку Data_String
66
	mov	EDI, Data_String
67
 
68
	; Сдвигаем число влево на NumberSymbolsAD
69
	; десятичных разрядов
70
	fninit		       ;сброс сопроцессора
71
	fld	[Data_Double]  ;загрузить число
72
	xor ebx,ebx
73
	mov	BX,[NumberSymbolsAD]
74
	cmp	BX, 0
75
	je	.NoShifts     ;нет цифр после запятой
76
	jl	.Error	      ;ошибка
77
	dec	BX
78
	shl	BX, 3		;умножаем на 8
79
	add	EBX, MConst
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
200
	; Заносим в SI указатель на строку
201
	mov	ESI, Data_String
202
	; Пропускаем пробелы перед числом
203
	mov	ecx,64 ;защита от зацикливания
204
.ShiftIgnore:
205
	lodsb
206
	cmp	AL,' '
207
	jne	.ShiftIgnoreEnd
208
	loop	.ShiftIgnore
209
	jmp	.Error
7128 IgorA 210
align 4
2165 IgorA 211
.ShiftIgnoreEnd:
212
	; Проверяем знак числа
213
	cmp	AL,'-'
214
	jne	.Positive
215
	mov	[Data_Sign],80h
216
	lodsb
217
.Positive:
218
	mov	[Data_Flag],0 ;признак наличия точки
219
	mov	DX,0	      ;позиция точки
220
	mov	ecx,18	      ;макс. число разрядов
221
.ASCIItoBCDConversion:
222
	cmp	AL,'.'	      ;точка?
223
	jne	.NotDot
224
	cmp	[Data_Flag],0 ;точка не встречалась?
225
	jne	.Error
226
	mov	[Data_Flag],1
227
	lodsb
228
	cmp	AL,0	      ;конец строки?
229
	jne	.NotDot
230
	jmp	.ASCIItoBCDConversionEnd
7128 IgorA 231
align 4
2165 IgorA 232
.NotDot:
233
	; Увеличить на 1 значение позиции точки,
234
	; если она еще не встречалась
235
	cmp	[Data_Flag],0
236
	jnz	.Figures
237
	inc	DX
238
.Figures:
239
	; Символы числа должны быть цифрами
240
	cmp	AL,'0'
241
	jb	.Error
242
	cmp	AL,'9'
243
	ja	.Error
244
	; Пишем очередную цифру в младшую тетраду BCD
245
	and	AL,0Fh
246
	or	byte [Data_BCD],AL
247
	; Проверка на конец строки
248
	cmp	byte [ESI],0
249
	je	.ASCIItoBCDConversionEnd
250
	; Сдвигаем BCD на 4 разряда влево
251
	; (сдвигаем старшие 2 байта)
252
	mov	AX,word [Data_BCD+6]
253
	shld	word [Data_BCD+8],AX,4
254
	; (сдвигаем средние 4 байта)
255
	mov	EAX, dword [Data_BCD]
256
	shld	dword [Data_BCD+4],EAX,4
257
	; (сдвигаем младшие 4 байта)
258
	shl	dword [Data_BCD],4
259
	; Загружаем следующий символ в AL
260
	lodsb
261
	loop	.ASCIItoBCDConversion
262
	; Если 19-й символ не 0 и не точка,
263
	; то ошибка переполнения
264
	cmp	AL,'.'
265
	jne	.NotDot2
266
	inc	ecx
267
	lodsb
268
.NotDot2:
269
	cmp	AL,0
270
	jne	.Error ;переполнение разрядной сетки
271
 
272
; ПРЕОБРАЗОВАТЬ ЧИСЛО ИЗ КОДА BCD В ВЕЩЕСТВЕННОЕ ЧИСЛО
273
.ASCIItoBCDConversionEnd:
274
	; Вписать знак в старший байт
275
	mov	AL,[Data_Sign]
276
	mov	byte [Data_BCD+9],AL
277
	; Сбросить регистры сопроцессора
278
	fninit
279
	; Загрузить в сопроцессор число в BCD-формате
280
	fbld	[Data_BCD]
281
	; Вычислить номер делителя
282
	mov	EBX,18+1
283
	sub	BX,CX
284
	sub	BX,DX
285
	cmp	EBX,0
286
	je	.NoDiv
287
	dec	EBX
288
	shl	EBX,3		;умножаем на 8
289
	add	EBX, MConst
290
	fdiv	qword [EBX] ;разделить на константу
291
.NoDiv:; Выгрузить число в двоичном формате
292
	fstp	[Data_Double]
293
	jmp	.End
7128 IgorA 294
align 4
2165 IgorA 295
.Error:; При любой ошибке обнулить результат
296
	fldz	;занести ноль с стек сопроцессора
297
	fstp	[Data_Double]
298
.End:
299
	popad
300
	ret
301
 
302
align 4
7128 IgorA 303
proc str_cat uses eax ecx edi esi, str1:dword, str2:dword
2165 IgorA 304
	mov esi,dword[str2]
305
	stdcall str_len,esi
306
	mov ecx,eax
307
	inc ecx
308
	mov edi,dword[str1]
309
	stdcall str_len,edi
310
	add edi,eax
311
	cld
312
	repne movsb
313
	ret
314
endp
315
 
316
;output:
317
; eax = strlen
318
align 4
319
proc str_len, str1:dword
320
	mov eax,[str1]
321
	@@:
322
		cmp byte[eax],0
323
		je @f
324
		inc eax
325
		jmp @b
326
	@@:
327
	sub eax,[str1]
328
	ret
7128 IgorA 329
endp
330
 
331
align 4
332
proc String_crop_0 uses eax ebx ecx edi
333
	mov edi,Data_String
334
	mov al,'.'
335
	mov ecx,32
336
	repne scasb
337
	mov ebx,edi
338
	mov edi,Data_String
339
	xor al,al
340
	mov ecx,32
341
	repne scasb
342
	cmp ebx,edi
343
	jg .end_f
344
	dec edi
345
	.cycle0:
346
		dec edi
347
		cmp edi,Data_String
348
		jle .end_f
349
		cmp byte[edi],'0'
350
		jne .cycle0end
351
		mov byte[edi],0
352
		jmp .cycle0
353
	.cycle0end:
354
	cmp byte[edi],'.'
355
	jne .end_f
356
		mov byte[edi],0
357
	.end_f:
358
	ret
2165 IgorA 359
endp