- Move source code from `trunk` into root directory for each library. - Update build files and ASM include paths. Add SPDX license header where appropriate. - Note: Line endings standardised from `CRLF` > `LF`, so best to view diffs with whitespace changes hidden. (Work towards #75, point 3) Reviewed-on: KolibriOS/kolibrios#436 Reviewed-by: Burer <burer@kolibrios.org> Reviewed-by: Ivan B <1+dunkaist@noreply.localhost> Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com> Co-authored-by: Andrew <dent.ace@gmail.com> Co-committed-by: Andrew <dent.ace@gmail.com>
305 lines
7.5 KiB
FASM
305 lines
7.5 KiB
FASM
;-----------------------------------------------------------------------------+
|
|
; Функция перевода вещественного числа в строку [ 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 |