| Код | ; ***** ValToString: Подпрограмма форматирования числа типа Real в строку ****** ; [ebp+8] - Адрес строки(будет Zero-terminated) в виде 12345.89 ; [ebp+0Сh] - Адрес числа типа real (или dd) ; [ebp+10h] - Маска вывода числа (byte) ValToString proc .code push ebp mov ebp,esp ; Локальные переменные: ; [ebp-4] - модуль числа ; [ebp-08] - максимальная степень 10-ти в числе ; [ebp-0Ch] - временная sub esp,4*3 cld mov edi,dword ptr [ebp+8] ; Адрес выходной строки mov ebx,[ebp+0Ch] ; Загружаем адрес числа в ebx mov edx,[ebx] ; Читаем его в edx ; Определяем знак, удаляя его одновременно (31 бит) shl edx,1 jnc @@NoSign mov al,'-' stosb @@NoSign: shr edx,1 mov [ebp-4],edx ; Запоминаем модуль числа в локальной переменной ; Проверка на ноль test edx,edx jnz @@NonZero mov al,'0' stosb jmp @@DoneValToStr @@NonZero: ; Определяем старшую степень десяти - Log10(x) = Log2(x)/Log2(10) ; Выполняется в два приема, поскольку нет операции Log10 в FPU, а есть y*Log2(x) ; Получаем 1/Log2(10) fld1 ; Загрузить 1.0 fldl2t ; Загрузить log2(10) fdivp ST(1),ST(0) ; Разделить 1/log2(10), результат в ST(0) fld dword ptr [ebp-4] ; Загрузить наше число, 1/log2(10) протолкнуть в ST(1) fyl2x ; ST(0)=ST(1)*log2(ST(0)) ; Задаем режим округления (биты 11 - отбросить дробную часть) call Set_FPUTruncType frndint fistp dword ptr [ebp-8] ; Выгрузить степень как целое со знаком ; Задаем режим округления (биты 00 - округлить до ближайшего целого) call Set_FPURoundType ; Сохранить степень числа push dword ptr [ebp-8] ; Вывести число, деля его на 10^... ; Вывести целую часть числа, точку, дробную часть mov ecx,dword ptr [ebp+10h] ; Сколько цифр после десятичной точки выводить inc ecx ; Цифра перед десятичной точкой xor edx,edx ; Флаг вывода точки @@OutNumbers: fld dword ptr DecNumber ; Загрузить 10 - основание mov eax,dword ptr [ebp-8] ; Степень call get_pow ; ST(0) = 10^Степень fld dword ptr [ebp-4] ; Загрузить число ; ST(0)=Число, ST(1) = 10^Степень fdiv ST(0),ST(1) ; ST(0)=ST(0)/ST(1) ; Задаем режим округления (биты 11 - отбросить дробную часть) call Set_FPUTruncType frndint fistp dword ptr [ebp-0Ch] ; Выгружаем как целое без округления ; Задаем режим округления (биты 00 - округлить до ближайшего целого) call Set_FPURoundType ; Выводим цифру mov eax,dword ptr [ebp-0Ch] mov ebx,1 call DecChar ; В формате - @n1 inc edi ; Выводим точку, если это необходимо test edx,edx jnz @@PointAlreadyOut mov al,'.' stosb inc edx @@PointAlreadyOut: ; Вычесть из числа 10^Степень(сейчас в ST(0)) x Текущая цифра fimul dword ptr [ebp-0Ch] fld dword ptr [ebp-4] ; Загрузить число fsub ST(0),ST(1) fstp dword ptr [ebp-4] ; Выгрузить число с вычетом fstp ST(0) ; Очистить стек ; Уменьшить степень на 1 dec dword ptr [ebp-8] loop @@OutNumbers ; Восстановить степень числа pop dword ptr [ebp-8] ; Вывести степень 10-ти mov ax,'+E' mov edx,[ebp-8] cmp edx,0 jge @@NoNegPower neg edx mov ah,'-' @@NoNegPower: stosw mov eax,edx mov ebx,1000 call DecChar ; В формате @n4 add edi,4 @@DoneValToStr: mov byte ptr [edi],0 leave ret 3*4 ValToString endp
| |