;-----------------------------------------------------------------------------+ ; Функция перевода вещественного числа в строку [ by ManHunter / PCL ] | ;-----------------------------------------------------------------------------| ; Параметры: | ; lpFloat - указатель на вещественное число TBYTE | ; lpResult - указатель на строку-приемник результата | ;-----------------------------------------------------------------------------+ proc FloatToString lpFloat:DWORD, lpResult:DWORD ; Локальные переменные local digits_count:DWORD local old_cw:WORD local new_cw:WORD local saved_float:TBYTE local tmp1 rb 11h local tmp2 rb 11h ; Сохранить все регистры pusha ; Указатель на строку-приемник mov edi,[lpResult] ; Это ноль? mov esi,[lpFloat] cmp dword [esi],0 jne loc_not_zero cmp dword [esi+4],0 jne loc_not_zero cmp word [esi+8],0 jne loc_not_zero ; Записать в строку ноль mov al,'0' stosb jmp loc_ret loc_not_zero: ; Скопировать число в локальную переменную push edi mov esi,[lpFloat] lea edi,[saved_float] movsd movsd movsw pop edi ; Число отрицательное? cmp dword [saved_float+6],0 jge loc_not_signed ; Привести число к абсолютному значению and byte [saved_float+9],7Fh ; Записать в строку минус mov al,'-' stosb loc_not_signed: ; Проверить число на наличие дробной части и ; подсчитать количество цифр в нем fclex ; Сохранить управляющее слово fstcw [old_cw] ; Установить управляющее слово mov [new_cw],0000001001111111b fldcw [new_cw] lea esi,[saved_float] fld tbyte [esi] fld st ; Выделить мантиссу и порядок fxtract fstp st fldlg2 ; Получить количество цифр в числе fmulp st1,st fistp [digits_count] ; Если цифр больше 16, то число отображается в ; нормализованном виде с мантиссой и экспонентой cmp [digits_count],10h jnb loc_not_integer ; У числа есть дробная часть? fld st frndint fcomp st1 fstsw ax test ah,01000000b ; Да, отображать число с дробной частью jz loc_not_integer ; Целое число без дробной части и экспоненты lea eax,[tmp1] fbstp [eax] ; Перевести BCD-число в строку push edi lea esi,[tmp1+8] lea edi,[tmp2] mov ecx, 9 @@: std xor eax,eax lodsb cld rol ax,12 rol ah,4 add ax,'00' stosw loop @b pop edi ; Пропустить лидирующий ноль mov eax,11h mov ecx,[digits_count] sub eax,ecx inc ecx lea esi,[tmp2+eax] cmp byte [esi],'0' jne @f inc esi dec ecx @@: ; Перенести полученное число из временного буфера rep movsb jmp loc_clear_stack loc_not_integer: mov eax,10h sub eax,[digits_count] ; Преобразовать число в целое до 16 разрядов mov ecx,eax cmp eax,0 jge @f neg eax @@: ; Для чисел больше 0 корректировка округления в сторону 0 mov [new_cw],0000101001111111b cmp ecx,0 jge @f mov [new_cw],0000011001111111b @@: ; Установить управляющее слово fldcw [new_cw] ; Возвести 10 в степень количества цифр fld [float2] fld [float2] @@: fmul st,st1 dec eax cmp eax,1 ja @b ; Почистить стек fxch st1 fstp st ; Если число меньше 0, то умножить, иначе разделить cmp ecx,0 jge @f fdivp st1,st jmp loc_rounded @@: fmulp st1,st loc_rounded: ; Полученное значение меньше 1.0e16 ? fcom [float1] fstsw ax test ah,1 jz @f fmul [float2] dec [digits_count] @@: ; Целое число без дробной части и экспоненты lea eax,[tmp1] fbstp [eax] ; Перевести BCD-число в строку push edi lea esi,[tmp1+8] lea edi,[tmp2] mov ecx, 9 @@: std xor eax,eax lodsb cld rol ax,12 rol ah,4 add ax,'00' stosw loop @b pop edi ; Числу требуется мантисса и экспонента? lea esi,[tmp2+1] mov ecx,[digits_count] cmp ecx,-0Fh jl loc_mantiss_and_exponent cmp ecx,10h jg loc_mantiss_and_exponent ; Заполнить дробную часть числа inc ecx cmp ecx,0 jg @f mov ax,'0.' stosw neg ecx mov al,'0' rep stosb mov ecx,10h jmp loc_fraction_filled @@: rep movsb mov al,'.' stosb mov ecx,10h sub ecx,[digits_count] loc_fraction_filled: rep movsb jmp @f loc_clear_fraction: ; Удалить завершающие нули дробной части dec edi @@: cmp byte [edi-1],'0' jz loc_clear_fraction cmp byte [edi-1],'.' jnz @f dec edi @@: jmp loc_clear_stack loc_mantiss_and_exponent: ; Дробная часть мантиссы movsb mov al,'.' stosb movsd movsd movsw ; Удалить завершающие нули дробной части @@: cmp byte [edi-1],'0' jne @f cmp byte [edi-2],'.' je @f dec edi jmp @b @@: ; Символ и знак экспоненты mov al,'e' stosb mov al,'+' mov ebx,[digits_count] cmp ebx, 0 jge @f mov al,'-' neg ebx @@: stosb ; Значение экспоненты mov eax,ebx mov ecx,10 mov ebx,4 @@: dec ebx xor edx,edx div ecx add dl,'0' mov [tmp1+ebx],dl or ebx,ebx jnz @b ; Пропустить лидирующие нули экспоненты mov ecx,4 lea esi,[tmp1] @@: lodsb cmp al,'0' jne @f dec ecx jmp @b @@: dec esi rep movsb loc_clear_stack: ; Восстановить управляющее слово fldcw [old_cw] loc_ret: ; Окончание строки mov al,0 stosb ; Восстановить все регистры popa ret float1 dq 1.0e16 float2 dq 10.0 endp