Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5153 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
	lea 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
	lea eax,[MConst]
79
	add	EBX, eax
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
96
	mov	ebx,8	 ;смещение последней пары цифр
97
	mov	ecx,9	 ;счетчик пар цифр
98
	; Определить позицию десятичной точки в числе
99
	mov	DX,18
100
	sub	DX,[NumberSymbolsAD]
101
	js	.Error	;ошибка, если отрицательная
102
	jz	.Error	;или нулевая позиция
103
.NextPair:
104
	; Загрузить очередную пару разрядов
105
	mov	AL, byte [ebx + Data_BCD]
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
	lea	EDI, [Data_String]
134
	lea	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
; Скопировать значащую часть числа в начало строки
154
.N4:	rep movsb
155
	jmp    .End
156
 
157
; Ошибка
158
.Error:
159
	mov	AL,'E'
160
	stosb
161
	mov	AL,'R'
162
	stosb
163
	mov	AL,'R'
164
	stosb
165
	xor	AL,AL
166
	stosb
167
	jmp	.End
168
; Переполнение разрядной сетки
169
.Overflow:
170
	mov	AL,'#'
171
	stosb
172
	xor	AL,AL
173
	stosb
174
; Конец процедуры
175
.End:
176
	popad
177
	ret
178
 
179
;****************************************************
180
;* ПРЕОБРАЗОВАТЬ СТРОКУ В ЧИСЛО С ПЛАВАЮЩЕЙ ЗАПЯТОЙ *
181
;*      (число имеет обычный, "бытовой" формат)     *
182
;* Входные параметры:                               *
183
;* Data_String - число в коде ASCII.                *
184
;* Выходные параметры:                              *
185
;* Data_Double - число в двоичном коде.             *
186
;****************************************************
187
String_to_DoubleFloat:
188
	pushad
189
	cld
190
	; Очищаем Data_BCD
191
	mov dword [Data_BCD],0
192
	mov dword [Data_BCD+4],0
193
	mov  word [Data_BCD+8],0
194
	; Очищаем байт знака
195
	mov	[Data_Sign],0
196
	; Заносим в SI указатель на строку
197
	lea	ESI, [Data_String]
198
	; Пропускаем пробелы перед числом
199
	mov	ecx,64 ;защита от зацикливания
200
.ShiftIgnore:
201
	lodsb
202
	cmp	AL,' '
203
	jne	.ShiftIgnoreEnd
204
	loop	.ShiftIgnore
205
	jmp	.Error
206
.ShiftIgnoreEnd:
207
	; Проверяем знак числа
208
	cmp	AL,'-'
209
	jne	.Positive
210
	mov	[Data_Sign],80h
211
	lodsb
212
.Positive:
213
	mov	[Data_Flag],0 ;признак наличия точки
214
	mov	DX,0	      ;позиция точки
215
	mov	ecx,18	      ;макс. число разрядов
216
.ASCIItoBCDConversion:
217
	cmp	AL,'.'	      ;точка?
218
	jne	.NotDot
219
	cmp	[Data_Flag],0 ;точка не встречалась?
220
	jne	.Error
221
	mov	[Data_Flag],1
222
	lodsb
223
	cmp	AL,0	      ;конец строки?
224
	jne	.NotDot
225
	jmp	.ASCIItoBCDConversionEnd
226
.NotDot:
227
	; Увеличить на 1 значение позиции точки,
228
	; если она еще не встречалась
229
	cmp	[Data_Flag],0
230
	jnz	.Figures
231
	inc	DX
232
.Figures:
233
	; Символы числа должны быть цифрами
234
	cmp	AL,'0'
235
	jb	.Error
236
	cmp	AL,'9'
237
	ja	.Error
238
	; Пишем очередную цифру в младшую тетраду BCD
239
	and	AL,0Fh
240
	or	byte [Data_BCD],AL
241
	; Проверка на конец строки
242
	cmp	byte [ESI],0
243
	je	.ASCIItoBCDConversionEnd
244
	; Сдвигаем BCD на 4 разряда влево
245
	; (сдвигаем старшие 2 байта)
246
	mov	AX,word [Data_BCD+6]
247
	shld	word [Data_BCD+8],AX,4
248
	; (сдвигаем средние 4 байта)
249
	mov	EAX, dword [Data_BCD]
250
	shld	dword [Data_BCD+4],EAX,4
251
	; (сдвигаем младшие 4 байта)
252
	shl	dword [Data_BCD],4
253
	; Загружаем следующий символ в AL
254
	lodsb
255
	loop	.ASCIItoBCDConversion
256
	; Если 19-й символ не 0 и не точка,
257
	; то ошибка переполнения
258
	cmp	AL,'.'
259
	jne	.NotDot2
260
	inc	ecx
261
	lodsb
262
.NotDot2:
263
	cmp	AL,0
264
	jne	.Error ;переполнение разрядной сетки
265
 
266
; ПРЕОБРАЗОВАТЬ ЧИСЛО ИЗ КОДА BCD В ВЕЩЕСТВЕННОЕ ЧИСЛО
267
.ASCIItoBCDConversionEnd:
268
	; Вписать знак в старший байт
269
	mov	AL,[Data_Sign]
270
	mov	byte [Data_BCD+9],AL
271
	; Сбросить регистры сопроцессора
272
	fninit
273
	; Загрузить в сопроцессор число в BCD-формате
274
	fbld	[Data_BCD]
275
	; Вычислить номер делителя
276
	mov	EBX,18+1
277
	sub	BX,CX
278
	sub	BX,DX
279
	cmp	EBX,0
280
	je	.NoDiv
281
	dec	EBX
282
	shl	EBX,3		;умножаем на 8
283
	lea eax,[MConst]
284
	add	EBX,eax
285
	fdiv	qword [EBX] ;разделить на константу
286
.NoDiv:; Выгрузить число в двоичном формате
287
	fstp	[Data_Double]
288
	jmp	.End
289
 
290
.Error:; При любой ошибке обнулить результат
291
	fldz	;занести ноль с стек сопроцессора
292
	fstp	[Data_Double]
293
.End:
294
	popad
295
	ret
296
 
297
align 4
298
proc str_cat, str1:dword, str2:dword
299
	push eax ecx edi esi
300
	mov esi,dword[str2]
301
	stdcall str_len,esi
302
	mov ecx,eax
303
	inc ecx
304
	mov edi,dword[str1]
305
	stdcall str_len,edi
306
	add edi,eax
307
	cld
308
	repne movsb
309
	pop esi edi ecx eax
310
	ret
311
endp
312
 
313
;output:
314
; eax = strlen
315
align 4
316
proc str_len, str1:dword
317
	mov eax,[str1]
318
	@@:
319
		cmp byte[eax],0
320
		je @f
321
		inc eax
322
		jmp @b
323
	@@:
324
	sub eax,[str1]
325
	ret
326
endp