Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2162 IgorA 1
; Программа для преобразования чисел из строки
2
;   в формат float, double, а также из 10 или 16 ричного
3
;   во float.
4
; Сделана на основе hex2dec2bin и примеров из файла list2_05.inc
5
;   (автор Кулаков Владимир Геннадьевич 24.05.2002),
6
;   которые ChE переделал с 16 на 32 бита на ассемблер fasm.
7
; Программа позволяет решать такие задачи:
8
; 1) число в строковом виде перевести в 4 байта (float) в машинный вид
9
; 2) число в строковом виде перевести в 8 байт (double) в машинный вид
10
; 3) число в машинном виде (float) перевести в строковый вид (5 знаков после запятой)
11
 
12
use32
13
    org 0x0
14
    db	'MENUET01'
15
    dd	0x01,start,i_end,e_end,e_end,0,sys_path
16
 
17
include '../../../proc32.inc'
18
include '../../../macros.inc'
19
include '../../../develop/libraries/box_lib/load_lib.mac'
20
include '../../../develop/libraries/box_lib/trunk/box_lib.mac'
21
include 'lang.inc'
22
 
23
@use_library
24
 
25
align 4
26
start:
27
	load_libraries l_libs_start,l_libs_end
28
	;проверка на сколько удачно загузилась наша библиотека
29
	mov	ebp,lib_0
30
	cmp	dword [ebp+ll_struc_size-4],0
31
	jz	@f
32
		mcall -1 ;exit not correct
33
	@@:
34
	mcall 40,0x27
35
	mcall 48, 3, sys_colors, 40
36
	edit_boxes_set_sys_color edit1,editboxes_end,sys_colors
37
	option_boxes_set_sys_color sys_colors,Option_boxes1
38
 
39
align 4
40
red:
41
    call draw_window
42
 
43
align 4
44
still:
45
    mcall 10		; функция 10 - ждать события
46
 
47
    cmp  eax,1		; перерисовать окно ?
48
    je	 red		; если да - на метку red
49
    cmp  eax,2		; нажата клавиша ?
50
    je	 key		; если да - на key
51
    cmp  eax,3		; нажата кнопка ?
52
    je	 button 	; если да - на button
53
    cmp  eax,6
54
    je	 mouse
55
 
56
    jmp  still		; если другое событие - в начало цикла
57
 
58
;---------------------------------------------------------------------
59
key: ; нажата клавиша на клавиатуре
60
	mcall 2
61
	;cmp ah,13
62
	stdcall [edit_box_key], dword edit1
63
	jmp  still ; вернуться к началу цикла
64
 
65
; Количество знаков числа после запятой (1-17)
66
NumberSymbolsAD DW 5
67
; Константы (10 в степени N)
68
MConst DQ 1.0E1,1.0E2,1.0E3,1.0E4,1.0E5
69
       DQ 1.0E6,1.0E7,1.0E8,1.0E9,1.0E10
70
       DQ 1.0E11,1.0E12,1.0E13,1.0E14,1.0E15
71
       DQ 1.0E16,1.0E17,1.0E18,1.0E19,1.0E20
72
       DQ 1.0E21,1.0E22,1.0E23,1.0E24,1.0E25
73
       DQ 1.0E26,1.0E27,1.0E28,1.0E29,1.0E30
74
       DQ 1.0E31,1.0E32,1.0E33,1.0E34,1.0E35
75
       DQ 1.0E36,1.0E37,1.0E38,1.0E39,1.0E40
76
       DQ 1.0E41,1.0E42,1.0E43,1.0E44,1.0E45
77
       DQ 1.0E46,1.0E47,1.0E48,1.0E49,1.0E50
78
       DQ 1.0E51,1.0E52,1.0E53,1.0E54,1.0E55
79
       DQ 1.0E56,1.0E57,1.0E58,1.0E59,1.0E60
80
       DQ 1.0E61,1.0E62,1.0E63,1.0E64,1.0E65
81
       DQ 1.0E66,1.0E67,1.0E68,1.0E69,1.0E70
82
       DQ 1.0E71,1.0E72,1.0E73,1.0E74,1.0E75
83
       DQ 1.0E76,1.0E77,1.0E78,1.0E79,1.0E80
84
       DQ 1.0E81,1.0E82,1.0E83,1.0E84,1.0E85
85
       DQ 1.0E86,1.0E87,1.0E88,1.0E89,1.0E90
86
       DQ 1.0E91,1.0E92,1.0E93,1.0E94,1.0E95
87
       DQ 1.0E96,1.0E97,1.0E98,1.0E99,1.0E100
88
       DQ 1.0E101,1.0E102,1.0E103,1.0E104,1.0E105
89
       DQ 1.0E106,1.0E107,1.0E108,1.0E109,1.0E110
90
       DQ 1.0E111,1.0E112,1.0E113,1.0E114,1.0E115
91
       DQ 1.0E116,1.0E117,1.0E118,1.0E119,1.0E120
92
       DQ 1.0E121,1.0E122,1.0E123,1.0E124,1.0E125
93
       DQ 1.0E126,1.0E127,1.0E128
94
; Число с плавающей запятой двойной точности
95
Data_Double   DQ ?
96
; Число в BCD-формате
97
Data_BCD      DT ?
98
; Вспомогательный флаг
99
Data_Flag     DB ?
100
; Знак результата (если не 0 - отрицательное число)
101
Data_Sign     DB ?
102
; Строка для хранения числа в коде ASCII
103
Data_String   DB 32 DUP (?)
104
 
105
string1 db 32 dup (0)
106
string1_end:
107
 
108
 
109
 
110
;*******************************************************
111
;*  ПРЕОБРАЗОВАНИЕ ЧИСЛА С ПЛАВАЮЩЕЙ ЗАПЯТОЙ В СТРОКУ  *
112
;* Число имеет формат с удвоенной точностью, результат *
113
;* выдается в десятичном коде, в "бытовом" формате с   *
114
;* фиксированным количеством знаков после запятой.     *
115
;* Входные параметры:                                  *
116
;* Data_Double - преобразуемое число;                  *
117
;* NumberSymbolsAD - количество знаков после           *
118
;*                   запятой (0-17).                   *
119
;* Выходные параметры:                                 *
120
;* Data_String - строка-результат.                     *
121
;*******************************************************
122
DoubleFloat_to_String:
123
	pushad
124
	; Результат записывать в строку Data_String
125
	mov	EDI, Data_String
126
 
127
	; Сдвигаем число влево на NumberSymbolsAD
128
	; десятичных разрядов
129
	fninit		       ;сброс сопроцессора
130
	fld	[Data_Double]  ;загрузить число
131
	xor ebx,ebx
132
	mov	BX,[NumberSymbolsAD]
133
	cmp	BX, 0
134
	je	.NoShifts     ;нет цифр после запятой
135
	jl	.Error	      ;ошибка
136
	dec	BX
137
	shl	BX, 3		;умножаем на 8
138
	add	EBX, MConst
139
	fmul	qword [EBX] ;умножить на константу
140
.NoShifts:
141
	; Извлечь число в коде BCD
142
	fbstp	[Data_BCD]
143
; Проверить результат на переполнение
144
	mov	AX,word [Data_BCD + 8]
145
	cmp	AX,0FFFFh  ;"десятичное" переполнение?
146
	je	.Overflow
147
; Выделить знак числа и записать его в ASCII-коде
148
	mov	AL, byte [Data_BCD + 9]
149
	and	AL,AL
150
	jz	.NoSign
151
	mov	AL,'-'
152
	stosb
153
.NoSign:
154
; Распаковать число в код ASCII
2254 IgorA 155
	mov	ebx,8	 ;смещение последней пары цифр
2162 IgorA 156
	mov	ecx,9	 ;счетчик пар цифр
157
	; Определить позицию десятичной точки в числе
158
	mov	DX,18
159
	sub	DX,[NumberSymbolsAD]
160
	js	.Error	;ошибка, если отрицательная
161
	jz	.Error	;или нулевая позиция
162
.NextPair:
163
	; Загрузить очередную пару разрядов
2254 IgorA 164
	mov	AL, byte [ebx + Data_BCD]
2162 IgorA 165
	mov	AH,AL
166
	; Выделить, перевести в ASCII и
167
	; сохранить старшую тетраду
168
	shr	AL,4
169
	add	AL,'0'
170
	stosb
171
	dec	DX
172
	jnz	.N0
173
	mov	AL,'.'
174
	stosb
175
.N0:   ; Выделить, перевести в ASCII и
176
	; сохранить младшую тетраду
177
	mov	AL,AH
178
	and	AL,0Fh
179
	add	AL,'0'
180
	stosb
181
	dec	DX
182
	jnz	.N1
183
	mov	AL,'.'
184
	stosb
185
.N1:
186
	dec  BX
187
	loop .NextPair
188
	mov  AL,0
189
	stosb
190
 
191
; Убрать незначащие нули слева
192
	mov	EDI, Data_String
193
	mov	ESI, Data_String
194
	; Пропустить знак числа, если он есть
195
	cmp	byte [ESI],'-'
196
	jne	.N2
197
	inc	ESI
198
	inc	EDI
199
.N2:   ; Загрузить в счетчик цикла количество разрядов
200
	; числа плюс 1 (байт десятичной точки)
201
	mov	ecx,18+1+1
202
	; Пропустить незначащие нули
203
.N3:
204
	cmp byte [ESI],'0'
205
	jne .N4
206
	cmp byte [ESI+1],'.'
207
	je .N4
208
	inc ESI
209
	loop .N3
210
	; Ошибка - нет значащих цифр
211
	jmp	.Error
212
; Скопировать значащую часть числа в начало строки
213
.N4:	rep movsb
214
	jmp    .End
215
 
216
; Ошибка
217
.Error:
218
	mov	AL,'E'
219
	stosb
220
	mov	AL,'R'
221
	stosb
222
	mov	AL,'R'
223
	stosb
224
	xor	AL,AL
225
	stosb
226
	jmp	.End
227
; Переполнение разрядной сетки
228
.Overflow:
229
	mov	AL,'#'
230
	stosb
231
	xor	AL,AL
232
	stosb
233
; Конец процедуры
234
.End:
235
	popad
236
	ret
237
 
238
;****************************************************
239
;* ПРЕОБРАЗОВАТЬ СТРОКУ В ЧИСЛО С ПЛАВАЮЩЕЙ ЗАПЯТОЙ *
240
;*      (число имеет обычный, "бытовой" формат)     *
241
;* Входные параметры:                               *
242
;* Data_String - число в коде ASCII.                *
243
;* Выходные параметры:                              *
244
;* Data_Double - число в двоичном коде.             *
245
;****************************************************
246
String_to_DoubleFloat:
247
	pushad
248
	cld
249
	; Очищаем Data_BCD
250
	mov dword [Data_BCD],0
251
	mov dword [Data_BCD+4],0
252
	mov  word [Data_BCD+8],0
253
	; Очищаем байт знака
254
	mov	[Data_Sign],0
255
	; Заносим в SI указатель на строку
256
	mov	ESI, Data_String
257
	; Пропускаем пробелы перед числом
258
	mov	ecx,64 ;защита от зацикливания
259
.ShiftIgnore:
260
	lodsb
261
	cmp	AL,' '
262
	jne	.ShiftIgnoreEnd
263
	loop	.ShiftIgnore
264
	jmp	.Error
265
.ShiftIgnoreEnd:
266
	; Проверяем знак числа
267
	cmp	AL,'-'
268
	jne	.Positive
269
	mov	[Data_Sign],80h
270
	lodsb
271
.Positive:
272
	mov	[Data_Flag],0 ;признак наличия точки
273
	mov	DX,0	      ;позиция точки
274
	mov	ecx,18	      ;макс. число разрядов
275
.ASCIItoBCDConversion:
276
	cmp	AL,'.'	      ;точка?
277
	jne	.NotDot
278
	cmp	[Data_Flag],0 ;точка не встречалась?
279
	jne	.Error
280
	mov	[Data_Flag],1
281
	lodsb
282
	cmp	AL,0	      ;конец строки?
283
	jne	.NotDot
284
	jmp	.ASCIItoBCDConversionEnd
285
.NotDot:
286
	; Увеличить на 1 значение позиции точки,
287
	; если она еще не встречалась
288
	cmp	[Data_Flag],0
289
	jnz	.Figures
290
	inc	DX
291
.Figures:
292
	; Символы числа должны быть цифрами
293
	cmp	AL,'0'
294
	jb	.Error
295
	cmp	AL,'9'
296
	ja	.Error
297
	; Пишем очередную цифру в младшую тетраду BCD
298
	and	AL,0Fh
299
	or	byte [Data_BCD],AL
300
	; Проверка на конец строки
301
	cmp	byte [ESI],0
302
	je	.ASCIItoBCDConversionEnd
303
	; Сдвигаем BCD на 4 разряда влево
304
	; (сдвигаем старшие 2 байта)
305
	mov	AX,word [Data_BCD+6]
306
	shld	word [Data_BCD+8],AX,4
307
	; (сдвигаем средние 4 байта)
308
	mov	EAX, dword [Data_BCD]
309
	shld	dword [Data_BCD+4],EAX,4
310
	; (сдвигаем младшие 4 байта)
311
	shl	dword [Data_BCD],4
312
	; Загружаем следующий символ в AL
313
	lodsb
314
	loop	.ASCIItoBCDConversion
315
	; Если 19-й символ не 0 и не точка,
316
	; то ошибка переполнения
317
	cmp	AL,'.'
318
	jne	.NotDot2
319
	inc	ecx
320
	lodsb
321
.NotDot2:
322
	cmp	AL,0
323
	jne	.Error ;переполнение разрядной сетки
324
 
325
; ПРЕОБРАЗОВАТЬ ЧИСЛО ИЗ КОДА BCD В ВЕЩЕСТВЕННОЕ ЧИСЛО
326
.ASCIItoBCDConversionEnd:
327
	; Вписать знак в старший байт
328
	mov	AL,[Data_Sign]
329
	mov	byte [Data_BCD+9],AL
330
	; Сбросить регистры сопроцессора
331
	fninit
332
	; Загрузить в сопроцессор число в BCD-формате
333
	fbld	[Data_BCD]
334
	; Вычислить номер делителя
335
	mov	EBX,18+1
336
	sub	BX,CX
337
	sub	BX,DX
338
	cmp	EBX,0
339
	je	.NoDiv
340
	dec	EBX
341
	shl	EBX,3		;умножаем на 8
342
	add	EBX, MConst
343
	fdiv	qword [EBX] ;разделить на константу
344
.NoDiv:; Выгрузить число в двоичном формате
345
	fstp	[Data_Double]
346
	jmp	.End
347
 
348
.Error:; При любой ошибке обнулить результат
349
	fldz	;занести ноль с стек сопроцессора
350
	fstp	[Data_Double]
351
.End:
352
	popad
353
	ret
354
 
355
 
356
 
357
;input:
358
; buf - указатель на строку, число должно быть в 10 или 16 ричном виде
359
;output:
360
; eax - число
361
align 4
362
proc conv_str_to_int, buf:dword
363
	xor eax,eax
364
	push ebx ecx esi
365
	xor ebx,ebx
366
	mov esi,[buf]
367
	;определение отрицательных чисел
368
	xor ecx,ecx
369
	inc ecx
370
	cmp byte[esi],'-'
371
	jne @f
372
		dec ecx
373
		inc esi
374
	@@:
375
 
376
	cmp word[esi],'0x'
377
	je .load_digit_16
378
 
379
	.load_digit_10: ;считывание 10-тичных цифр
380
		mov bl,byte[esi]
381
		cmp bl,'0'
382
		jl @f
383
		cmp bl,'9'
384
		jg @f
385
			sub bl,'0'
386
			imul eax,10
387
			add eax,ebx
388
			inc esi
389
			jmp .load_digit_10
390
	jmp @f
391
 
392
	.load_digit_16: ;считывание 16-ричных цифр
393
		add esi,2
394
	.cycle_16:
395
		mov bl,byte[esi]
396
		cmp bl,'0'
397
		jl @f
398
		cmp bl,'f'
399
		jg @f
400
		cmp bl,'9'
401
		jle .us1
402
			cmp bl,'A'
403
			jl @f ;отсеиваем символы >'9' и <'A'
404
		.us1: ;составное условие
405
		cmp bl,'F'
406
		jle .us2
407
			cmp bl,'a'
408
			jl @f ;отсеиваем символы >'F' и <'a'
409
			sub bl,32 ;переводим символы в верхний регистр, для упрощения их последущей обработки
410
		.us2: ;составное условие
411
			sub bl,'0'
412
			cmp bl,9
413
			jle .cor1
414
				sub bl,7 ;convert 'A' to '10'
415
			.cor1:
416
			shl eax,4
417
			add eax,ebx
418
			inc esi
419
			jmp .cycle_16
420
	@@:
421
	cmp ecx,0 ;если число отрицательное
422
	jne @f
423
		sub ecx,eax
424
		mov eax,ecx
425
	@@:
426
	pop esi ecx ebx
427
	ret
428
endp
429
 
430
 
431
 
432
;---------------------------------------------------------------------
433
align 4
434
button:
435
	mcall 17		; 17 - получить идентификатор нажатой кнопки
436
	cmp   ah, 1	; если НЕ нажата кнопка с номером 1,
437
	jne   @f
438
		mcall -1
439
	@@:
440
	cmp ah, 5
441
	jne @f
442
		cmp dword[option_group1],opt3
443
		jne .opt_3_end
444
			stdcall conv_str_to_int,dword[edit1.text]
445
			mov dword[Data_Double],eax
446
			finit
447
			fld dword[Data_Double]
448
			fstp qword[Data_Double]
449
 
450
			; Data_Double - преобразуемое число
451
			; NumberSymbolsAD - количество знаков после запятой (0-17)
452
			call DoubleFloat_to_String
453
			mov dword[Data_Double],eax ;восстанавливаем значение в формате float
454
			jmp .opt_all_end
455
		.opt_3_end:
456
 
457
		mov esi,string1
458
		mov edi,Data_String
459
		cld
460
		mov ecx,32
461
		rep movsb
462
 
463
		call String_to_DoubleFloat
464
		cmp dword[option_group1],opt1
465
		jne .opt_all_end ;если выбран float, то преобразуем из ранее полученного double
466
			finit
467
			fld  qword[Data_Double] ;читаем из double
468
			fstp dword[Data_Double] ;а возвращаем во float
469
		.opt_all_end:
470
		jmp red
471
	@@:
472
	jmp still
473
 
474
mouse:
475
	stdcall [edit_box_mouse], edit1
476
	stdcall [option_box_mouse], Option_boxes1
477
	jmp still
478
 
479
;------------------------------------------------
480
align 4
481
draw_window:
482
	mcall 48, 3, sys_colors, sizeof.system_colors
483
 
484
	mcall 12, 1
485
	mov edx, 0x14000000
486
	or  edx, [sys_colors.work]
487
	mcall 0, 200*65536+300, 200*65536+175, ,,title
488
 
489
	mcall 8, (300-53)*65536+38,145*65536+ 15, 5,[sys_colors.work_button] ; кнопка Ok
490
 
491
	mov ecx, 0x80000000
492
	or  ecx, [sys_colors.work_text]
493
	mcall 4, 15*65536 +30,, binstr,
494
	mcall  , 15*65536 +58,, decstr,
495
		mcall  , (240-56*3)*65536 +58,, Data_String,
496
	mcall  , 15*65536 +72,, hexstr,
497
	mcall  , 15*65536+150,, numstr,
498
 
499
	mov ecx, 0x80000000
500
	or  ecx, [sys_colors.work_button_text]
501
	mcall  , (300-42)*65536+149,	, Okstr,3
502
 
503
	cmp dword[option_group1],opt1
504
	je @f ;если выбран float, то старшие 4 байта (из double) не печатаем
505
	cmp dword[option_group1],opt3
506
	je @f ;если выбран float, то старшие 4 байта (из double) не печатаем
507
		mov ecx, dword[Data_Double+4]
508
		mcall  47, 8*65536+256,,185*65536+72,[sys_colors.work_text]    ; 16-ная
509
 
510
		mov ecx, dword[Data_Double+4]
511
		mcall	 ,8*65536+512,,240*65536+30,	  ; 2-ная
512
		ror ecx, 8
513
		mcall	 ,,,(240-56)*65536+30,
514
		ror ecx, 8
515
		mcall	 ,,,(240-56*2)*65536+30,
516
		ror ecx, 8
517
		mcall	 ,,,(240-56*3)*65536+30,
518
		ror ecx, 8
519
	@@:
520
 
521
	mov ecx,dword[Data_Double]
522
	mcall  47, 8*65536+256,,240*65536+72,[sys_colors.work_text]	 ; 16-ная
523
 
524
	mov ecx,dword[Data_Double]
525
	mcall	 , 8*65536+512,,240*65536+44,	  ; 2-ная
526
	ror ecx, 8
527
	mcall	 ,,,(240-56)*65536+44,
528
	ror ecx, 8
529
	mcall	 ,,,(240-56*2)*65536+44,
530
	ror ecx, 8
531
	mcall	 ,,,(240-56*3)*65536+44,
532
	ror ecx, 8
533
 
534
	mcall 38, 15*65536+300-15, 137*65536+137, [sys_colors.work_graph]
535
	stdcall [edit_box_draw], edit1
536
	stdcall [option_box_draw], Option_boxes1
537
	mcall 12, 2		   ; функция 12: сообщить ОС об отрисовке окна
538
 
539
ret
540
 
541
 
542
;-------------------------------------------------
543
title db 'string to double 07.09.11',0
544
hexstr db 'hex:',0
545
decstr db 'dec:',0
546
binstr db 'bin:',0
547
 
548
if lang eq ru
549
	numstr db 'Число:',0
550
	Okstr db 'Ввод',0
551
	head_f_i:
552
	head_f_l db 'Системная ошибка',0
553
else
554
	numstr db 'Number:',0
555
	Okstr db 'Ok',0
556
	head_f_i:
557
	head_f_l db 'System error',0
558
end if
559
 
560
mouse_dd dd 0
561
edit1 edit_box 182, 59, 146, 0xffffff, 0xff, 0x80ff, 0, 0x8000, (string1_end-string1), string1, mouse_dd, 0
562
editboxes_end:
563
 
564
;option_boxes
565
opt1 option_box option_group1, 15,  90, 8, 12, 0xffffff, 0x80ff, 0, op_text.1, 17
566
opt2 option_box option_group1, 15, 106, 8, 12, 0xffffff, 0x80ff, 0, op_text.2, 18
567
opt3 option_box option_group1, 15, 122, 8, 12, 0xffffff, 0x80ff, 0, op_text.3, 21
568
 
569
op_text: ;текст для радио кнопок
570
  .1 db 'str(dec) -> float'
571
  .2 db 'str(dec) -> double'
572
  .3 db 'float(dec,hex) -> str'
573
;указатели для option_box
574
option_group1 dd opt1
575
Option_boxes1 dd opt1, opt2, opt3, 0
576
 
577
system_dir_0 db '/sys/lib/'
578
lib_name_0 db 'box_lib.obj',0
579
err_msg_found_lib_0 db 'Не найдена библиотека ',39,'box_lib.obj',39,0
580
err_msg_import_0 db 'Ошибка при импорте библиотеки ',39,'box_lib',39,0
581
 
582
l_libs_start:
583
	lib_0 l_libs lib_name_0, sys_path, library_path, system_dir_0,\
584
		err_msg_found_lib_0,head_f_l,import_box_lib,err_msg_import_0,head_f_i
585
l_libs_end:
586
 
587
align 4
588
import_box_lib:
589
	;dd sz_init1
590
	edit_box_draw dd sz_edit_box_draw
591
	edit_box_key dd sz_edit_box_key
592
	edit_box_mouse dd sz_edit_box_mouse
593
	;edit_box_set_text dd sz_edit_box_set_text
594
	option_box_draw dd aOption_box_draw
595
	option_box_mouse dd aOption_box_mouse
596
	;version_op dd aVersion_op
597
dd 0,0
598
	;sz_init1 db 'lib_init',0
599
	sz_edit_box_draw db 'edit_box',0
600
	sz_edit_box_key db 'edit_box_key',0
601
	sz_edit_box_mouse db 'edit_box_mouse',0
602
	;sz_edit_box_set_text db 'edit_box_set_text',0
603
	aOption_box_draw db 'option_box_draw',0
604
	aOption_box_mouse db 'option_box_mouse',0
605
	;aVersion_op db 'version_op',0
606
 
607
i_end:
608
	sys_colors system_colors
609
	rb 0x400 ;stack
610
	sys_path rb 4096
611
	library_path rb 4096
612
e_end: ; метка конца программы