Subversion Repositories Kolibri OS

Rev

Rev 4721 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4721 Akyltist 1
;-----------------------------------------------------------------------------+
2
; Функция перевода вещественного числа в строку      [ by ManHunter / PCL ]   |
3
;-----------------------------------------------------------------------------|
4
; Параметры:                                                                  |
5
;   lpFloat - указатель на вещественное число TBYTE                           |
6
;   lpResult - указатель на строку-приемник результата                        |
7
;-----------------------------------------------------------------------------+
8
 
9
proc    FloatToString lpFloat:DWORD, lpResult:DWORD
4887 Akyltist 10
        ; Локальные переменные
11
        local   digits_count:DWORD
12
        local   old_cw:WORD
13
        local   new_cw:WORD
14
        local   saved_float:TBYTE
15
        local   tmp1 rb 11h
16
        local   tmp2 rb 11h
17
 
18
        ; Сохранить все регистры
19
        pusha
20
 
21
        ; Указатель на строку-приемник
22
        mov     edi,[lpResult]
23
 
24
        ; Это ноль?
25
        mov     esi,[lpFloat]
26
        cmp     dword [esi],0
27
        jne     loc_not_zero
28
        cmp     dword [esi+4],0
29
        jne     loc_not_zero
30
        cmp     word [esi+8],0
31
        jne     loc_not_zero
32
        ; Записать в строку ноль
33
        mov     al,'0'
34
        stosb
35
        jmp     loc_ret
36
 
4721 Akyltist 37
loc_not_zero:
4887 Akyltist 38
        ; Скопировать число в локальную переменную
39
        push    edi
40
        mov     esi,[lpFloat]
41
        lea     edi,[saved_float]
42
        movsd
43
        movsd
44
        movsw
45
        pop     edi
46
        ; Число отрицательное?
47
        cmp     dword [saved_float+6],0
48
        jge     loc_not_signed
49
        ; Привести число к абсолютному значению
50
        and     byte [saved_float+9],7Fh
51
        ; Записать в строку минус
52
        mov     al,'-'
53
        stosb
54
 
4721 Akyltist 55
loc_not_signed:
4887 Akyltist 56
        ; Проверить число на наличие дробной части и
57
        ; подсчитать количество цифр в нем
58
        fclex
59
        ; Сохранить управляющее слово
60
        fstcw   [old_cw]
61
        ; Установить управляющее слово
62
        mov     [new_cw],0000001001111111b
63
        fldcw   [new_cw]
64
        lea     esi,[saved_float]
65
        fld     tbyte [esi]
66
        fld     st
67
        ; Выделить мантиссу и порядок
68
        fxtract
69
        fstp    st
70
        fldlg2
71
        ; Получить количество цифр в числе
72
        fmulp   st1,st
73
        fistp   [digits_count]
74
        ; Если цифр больше 16, то число отображается в
75
        ; нормализованном виде с мантиссой и экспонентой
76
        cmp     [digits_count],10h
77
        jnb     loc_not_integer
78
        ; У числа есть дробная часть?
79
        fld     st
80
        frndint
81
        fcomp   st1
82
        fstsw   ax
83
        test    ah,01000000b
84
        ; Да, отображать число с дробной частью
85
        jz      loc_not_integer
86
 
87
        ; Целое число без дробной части и экспоненты
88
        lea     eax,[tmp1]
89
        fbstp   [eax]
90
 
91
        ; Перевести BCD-число в строку
92
        push    edi
93
        lea     esi,[tmp1+8]
94
        lea     edi,[tmp2]
95
        mov     ecx, 9
4721 Akyltist 96
@@:
4887 Akyltist 97
        std
98
        xor     eax,eax
99
        lodsb
100
        cld
101
        rol     ax,12
102
        rol     ah,4
103
        add     ax,'00'
104
        stosw
105
        loop    @b
106
        pop     edi
107
 
108
        ; Пропустить лидирующий ноль
109
        mov     eax,11h
110
        mov     ecx,[digits_count]
111
        sub     eax,ecx
112
        inc     ecx
113
        lea     esi,[tmp2+eax]
114
        cmp     byte [esi],'0'
115
        jne     @f
116
        inc     esi
117
        dec     ecx
4721 Akyltist 118
@@:
4887 Akyltist 119
        ; Перенести полученное число из временного буфера
120
        rep     movsb
121
        jmp     loc_clear_stack
122
 
4721 Akyltist 123
loc_not_integer:
4887 Akyltist 124
        mov     eax,10h
125
        sub     eax,[digits_count]
126
 
127
        ; Преобразовать число в целое до 16 разрядов
128
        mov     ecx,eax
129
        cmp     eax,0
130
        jge     @f
131
        neg     eax
4721 Akyltist 132
@@:
4887 Akyltist 133
        ; Для чисел больше 0 корректировка округления в сторону 0
134
        mov     [new_cw],0000101001111111b
135
        cmp     ecx,0
136
        jge     @f
137
        mov     [new_cw],0000011001111111b
4721 Akyltist 138
@@:
4887 Akyltist 139
        ; Установить управляющее слово
140
        fldcw   [new_cw]
141
 
142
        ; Возвести 10 в степень количества цифр
143
        fld     [float2]
144
        fld     [float2]
4721 Akyltist 145
@@:
4887 Akyltist 146
        fmul    st,st1
147
        dec     eax
148
        cmp     eax,1
149
        ja      @b
150
 
151
        ; Почистить стек
152
        fxch    st1
153
        fstp    st
154
 
155
        ; Если число меньше 0, то умножить, иначе разделить
156
        cmp     ecx,0
157
        jge     @f
158
        fdivp   st1,st
159
        jmp     loc_rounded
4721 Akyltist 160
@@:
4887 Akyltist 161
        fmulp   st1,st
162
 
4721 Akyltist 163
loc_rounded:
4887 Akyltist 164
        ; Полученное значение меньше 1.0e16 ?
165
        fcom    [float1]
166
        fstsw   ax
167
        test    ah,1
168
        jz      @f
169
        fmul    [float2]
170
        dec     [digits_count]
4721 Akyltist 171
@@:
4887 Akyltist 172
        ; Целое число без дробной части и экспоненты
173
        lea     eax,[tmp1]
174
        fbstp   [eax]
175
 
176
        ; Перевести BCD-число в строку
177
        push    edi
178
        lea     esi,[tmp1+8]
179
        lea     edi,[tmp2]
180
        mov     ecx, 9
4721 Akyltist 181
@@:
4887 Akyltist 182
        std
183
        xor     eax,eax
184
        lodsb
185
        cld
186
        rol     ax,12
187
        rol     ah,4
188
        add     ax,'00'
189
        stosw
190
        loop    @b
191
        pop     edi
192
 
193
        ; Числу требуется мантисса и экспонента?
194
        lea     esi,[tmp2+1]
195
        mov     ecx,[digits_count]
196
        cmp     ecx,-0Fh
197
        jl      loc_mantiss_and_exponent
198
        cmp     ecx,10h
199
        jg      loc_mantiss_and_exponent
200
 
201
        ; Заполнить дробную часть числа
202
        inc     ecx
203
        cmp     ecx,0
204
        jg      @f
205
        mov     ax,'0.'
206
        stosw
207
        neg     ecx
208
        mov     al,'0'
209
        rep     stosb
210
        mov     ecx,10h
211
        jmp     loc_fraction_filled
4721 Akyltist 212
@@:
4887 Akyltist 213
        rep     movsb
214
        mov     al,'.'
215
        stosb
216
        mov     ecx,10h
217
        sub     ecx,[digits_count]
218
 
4721 Akyltist 219
loc_fraction_filled:
4887 Akyltist 220
        rep     movsb
221
        jmp     @f
222
 
4721 Akyltist 223
loc_clear_fraction:
4887 Akyltist 224
        ; Удалить завершающие нули дробной части
225
        dec     edi
4721 Akyltist 226
@@:
4887 Akyltist 227
        cmp     byte [edi-1],'0'
228
        jz      loc_clear_fraction
229
        cmp     byte [edi-1],'.'
230
        jnz     @f
231
        dec     edi
4721 Akyltist 232
@@:
4887 Akyltist 233
        jmp     loc_clear_stack
234
 
4721 Akyltist 235
loc_mantiss_and_exponent:
4887 Akyltist 236
        ; Дробная часть мантиссы
237
        movsb
238
        mov     al,'.'
239
        stosb
240
        movsd
241
        movsd
242
        movsw
243
        ; Удалить завершающие нули дробной части
4721 Akyltist 244
@@:
4887 Akyltist 245
        cmp     byte [edi-1],'0'
246
        jne     @f
247
        cmp     byte [edi-2],'.'
248
        je      @f
249
        dec     edi
250
        jmp     @b
4721 Akyltist 251
@@:
4887 Akyltist 252
        ; Символ и знак экспоненты
253
        mov     al,'e'
254
        stosb
255
        mov     al,'+'
256
        mov     ebx,[digits_count]
257
        cmp     ebx, 0
258
        jge     @f
259
        mov     al,'-'
260
        neg     ebx
4721 Akyltist 261
@@:
4887 Akyltist 262
        stosb
263
 
264
        ; Значение экспоненты
265
        mov     eax,ebx
266
        mov     ecx,10
267
        mov     ebx,4
4721 Akyltist 268
@@:
4887 Akyltist 269
        dec     ebx
270
        xor     edx,edx
271
        div     ecx
272
        add     dl,'0'
273
        mov     [tmp1+ebx],dl
274
        or      ebx,ebx
275
        jnz     @b
276
 
277
        ; Пропустить лидирующие нули экспоненты
278
        mov     ecx,4
279
        lea     esi,[tmp1]
4721 Akyltist 280
@@:
4887 Akyltist 281
        lodsb
282
        cmp     al,'0'
283
        jne     @f
284
        dec     ecx
285
        jmp     @b
4721 Akyltist 286
@@:
4887 Akyltist 287
        dec     esi
288
        rep     movsb
289
 
4721 Akyltist 290
loc_clear_stack:
4887 Akyltist 291
        ; Восстановить управляющее слово
292
        fldcw   [old_cw]
4721 Akyltist 293
loc_ret:
4887 Akyltist 294
        ; Окончание строки
295
        mov     al,0
296
        stosb
297
 
298
        ; Восстановить все регистры
299
        popa
300
        ret
301
 
4721 Akyltist 302
float1  dq      1.0e16
303
float2  dq      10.0
4887 Akyltist 304
 
4721 Akyltist 305
endp