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 |