Subversion Repositories Kolibri OS

Rev

Rev 2165 | 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 ?
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
;*******************************************************
62
DoubleFloat_to_String:
63
	pushad
64
	; Результат записывать в строку Data_String
65
	mov	EDI, Data_String
66
 
67
	; Сдвигаем число влево на NumberSymbolsAD
68
	; десятичных разрядов
69
	fninit		       ;сброс сопроцессора
70
	fld	[Data_Double]  ;загрузить число
71
	xor ebx,ebx
72
	mov	BX,[NumberSymbolsAD]
73
	cmp	BX, 0
74
	je	.NoShifts     ;нет цифр после запятой
75
	jl	.Error	      ;ошибка
76
	dec	BX
77
	shl	BX, 3		;умножаем на 8
78
	add	EBX, MConst
79
	fmul	qword [EBX] ;умножить на константу
80
.NoShifts:
81
	; Извлечь число в коде BCD
82
	fbstp	[Data_BCD]
83
; Проверить результат на переполнение
84
	mov	AX,word [Data_BCD + 8]
85
	cmp	AX,0FFFFh  ;"десятичное" переполнение?
86
	je	.Overflow
87
; Выделить знак числа и записать его в ASCII-коде
88
	mov	AL, byte [Data_BCD + 9]
89
	and	AL,AL
90
	jz	.NoSign
91
	mov	AL,'-'
92
	stosb
93
.NoSign:
94
; Распаковать число в код ASCII
2254 IgorA 95
	mov	ebx,8	 ;смещение последней пары цифр
2165 IgorA 96
	mov	ecx,9	 ;счетчик пар цифр
97
	; Определить позицию десятичной точки в числе
98
	mov	DX,18
99
	sub	DX,[NumberSymbolsAD]
100
	js	.Error	;ошибка, если отрицательная
101
	jz	.Error	;или нулевая позиция
102
.NextPair:
103
	; Загрузить очередную пару разрядов
2254 IgorA 104
	mov	AL, byte [ebx + Data_BCD]
2165 IgorA 105
	mov	AH,AL
106
	; Выделить, перевести в ASCII и
107
	; сохранить старшую тетраду
108
	shr	AL,4
109
	add	AL,'0'
110
	stosb
111
	dec	DX
112
	jnz	.N0
113
	mov	AL,'.'
114
	stosb
115
.N0:   ; Выделить, перевести в ASCII и
116
	; сохранить младшую тетраду
117
	mov	AL,AH
118
	and	AL,0Fh
119
	add	AL,'0'
120
	stosb
121
	dec	DX
122
	jnz	.N1
123
	mov	AL,'.'
124
	stosb
125
.N1:
126
	dec  BX
127
	loop .NextPair
128
	mov  AL,0
129
	stosb
130
 
131
; Убрать незначащие нули слева
132
	mov	EDI, Data_String
133
	mov	ESI, Data_String
134
	; Пропустить знак числа, если он есть
135
	cmp	byte [ESI],'-'
136
	jne	.N2
137
	inc	ESI
138
	inc	EDI
139
.N2:   ; Загрузить в счетчик цикла количество разрядов
140
	; числа плюс 1 (байт десятичной точки)
141
	mov	ecx,18+1+1
142
	; Пропустить незначащие нули
143
.N3:
144
	cmp byte [ESI],'0'
145
	jne .N4
146
	cmp byte [ESI+1],'.'
147
	je .N4
148
	inc ESI
149
	loop .N3
150
	; Ошибка - нет значащих цифр
151
	jmp	.Error
152
; Скопировать значащую часть числа в начало строки
153
.N4:	rep movsb
154
	jmp    .End
155
 
156
; Ошибка
157
.Error:
158
	mov	AL,'E'
159
	stosb
160
	mov	AL,'R'
161
	stosb
162
	mov	AL,'R'
163
	stosb
164
	xor	AL,AL
165
	stosb
166
	jmp	.End
167
; Переполнение разрядной сетки
168
.Overflow:
169
	mov	AL,'#'
170
	stosb
171
	xor	AL,AL
172
	stosb
173
; Конец процедуры
174
.End:
175
	popad
176
	ret
177
 
178
;****************************************************
179
;* ПРЕОБРАЗОВАТЬ СТРОКУ В ЧИСЛО С ПЛАВАЮЩЕЙ ЗАПЯТОЙ *
180
;*      (число имеет обычный, "бытовой" формат)     *
181
;* Входные параметры:                               *
182
;* Data_String - число в коде ASCII.                *
183
;* Выходные параметры:                              *
184
;* Data_Double - число в двоичном коде.             *
185
;****************************************************
186
String_to_DoubleFloat:
187
	pushad
188
	cld
189
	; Очищаем Data_BCD
190
	mov dword [Data_BCD],0
191
	mov dword [Data_BCD+4],0
192
	mov  word [Data_BCD+8],0
193
	; Очищаем байт знака
194
	mov	[Data_Sign],0
195
	; Заносим в SI указатель на строку
196
	mov	ESI, Data_String
197
	; Пропускаем пробелы перед числом
198
	mov	ecx,64 ;защита от зацикливания
199
.ShiftIgnore:
200
	lodsb
201
	cmp	AL,' '
202
	jne	.ShiftIgnoreEnd
203
	loop	.ShiftIgnore
204
	jmp	.Error
205
.ShiftIgnoreEnd:
206
	; Проверяем знак числа
207
	cmp	AL,'-'
208
	jne	.Positive
209
	mov	[Data_Sign],80h
210
	lodsb
211
.Positive:
212
	mov	[Data_Flag],0 ;признак наличия точки
213
	mov	DX,0	      ;позиция точки
214
	mov	ecx,18	      ;макс. число разрядов
215
.ASCIItoBCDConversion:
216
	cmp	AL,'.'	      ;точка?
217
	jne	.NotDot
218
	cmp	[Data_Flag],0 ;точка не встречалась?
219
	jne	.Error
220
	mov	[Data_Flag],1
221
	lodsb
222
	cmp	AL,0	      ;конец строки?
223
	jne	.NotDot
224
	jmp	.ASCIItoBCDConversionEnd
225
.NotDot:
226
	; Увеличить на 1 значение позиции точки,
227
	; если она еще не встречалась
228
	cmp	[Data_Flag],0
229
	jnz	.Figures
230
	inc	DX
231
.Figures:
232
	; Символы числа должны быть цифрами
233
	cmp	AL,'0'
234
	jb	.Error
235
	cmp	AL,'9'
236
	ja	.Error
237
	; Пишем очередную цифру в младшую тетраду BCD
238
	and	AL,0Fh
239
	or	byte [Data_BCD],AL
240
	; Проверка на конец строки
241
	cmp	byte [ESI],0
242
	je	.ASCIItoBCDConversionEnd
243
	; Сдвигаем BCD на 4 разряда влево
244
	; (сдвигаем старшие 2 байта)
245
	mov	AX,word [Data_BCD+6]
246
	shld	word [Data_BCD+8],AX,4
247
	; (сдвигаем средние 4 байта)
248
	mov	EAX, dword [Data_BCD]
249
	shld	dword [Data_BCD+4],EAX,4
250
	; (сдвигаем младшие 4 байта)
251
	shl	dword [Data_BCD],4
252
	; Загружаем следующий символ в AL
253
	lodsb
254
	loop	.ASCIItoBCDConversion
255
	; Если 19-й символ не 0 и не точка,
256
	; то ошибка переполнения
257
	cmp	AL,'.'
258
	jne	.NotDot2
259
	inc	ecx
260
	lodsb
261
.NotDot2:
262
	cmp	AL,0
263
	jne	.Error ;переполнение разрядной сетки
264
 
265
; ПРЕОБРАЗОВАТЬ ЧИСЛО ИЗ КОДА BCD В ВЕЩЕСТВЕННОЕ ЧИСЛО
266
.ASCIItoBCDConversionEnd:
267
	; Вписать знак в старший байт
268
	mov	AL,[Data_Sign]
269
	mov	byte [Data_BCD+9],AL
270
	; Сбросить регистры сопроцессора
271
	fninit
272
	; Загрузить в сопроцессор число в BCD-формате
273
	fbld	[Data_BCD]
274
	; Вычислить номер делителя
275
	mov	EBX,18+1
276
	sub	BX,CX
277
	sub	BX,DX
278
	cmp	EBX,0
279
	je	.NoDiv
280
	dec	EBX
281
	shl	EBX,3		;умножаем на 8
282
	add	EBX, MConst
283
	fdiv	qword [EBX] ;разделить на константу
284
.NoDiv:; Выгрузить число в двоичном формате
285
	fstp	[Data_Double]
286
	jmp	.End
287
 
288
.Error:; При любой ошибке обнулить результат
289
	fldz	;занести ноль с стек сопроцессора
290
	fstp	[Data_Double]
291
.End:
292
	popad
293
	ret
294
 
295
align 4
296
proc str_cat, str1:dword, str2:dword
297
	push eax ecx edi esi
298
	mov esi,dword[str2]
299
	stdcall str_len,esi
300
	mov ecx,eax
301
	inc ecx
302
	mov edi,dword[str1]
303
	stdcall str_len,edi
304
	add edi,eax
305
	cld
306
	repne movsb
307
	pop esi edi ecx eax
308
	ret
309
endp
310
 
311
;output:
312
; eax = strlen
313
align 4
314
proc str_len, str1:dword
315
	mov eax,[str1]
316
	@@:
317
		cmp byte[eax],0
318
		je @f
319
		inc eax
320
		jmp @b
321
	@@:
322
	sub eax,[str1]
323
	ret
324
endp