Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;-----------------------------------------------------------------------------+
  2. ; Функция перевода вещественного числа в строку      [ by ManHunter / PCL ]   |
  3. ;-----------------------------------------------------------------------------|
  4. ; Параметры:                                                                  |
  5. ;   lpFloat - указатель на вещественное число TBYTE                           |
  6. ;   lpResult - указатель на строку-приемник результата                        |
  7. ;-----------------------------------------------------------------------------+
  8.  
  9. proc    FloatToString lpFloat:DWORD, lpResult:DWORD
  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.     lea     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.  
  37. loc_not_zero:
  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.  
  55. loc_not_signed:
  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
  96. @@:
  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
  118. @@:
  119.     ; Перенести полученное число из временного буфера
  120.     rep     movsb
  121.     jmp     loc_clear_stack
  122.  
  123. loc_not_integer:
  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
  132. @@:
  133.     ; Для чисел больше 0 корректировка округления в сторону 0
  134.     mov     [new_cw],0000101001111111b
  135.     cmp     ecx,0
  136.     jge     @f
  137.     mov     [new_cw],0000011001111111b
  138. @@:
  139.     ; Установить управляющее слово
  140.     fldcw   [new_cw]
  141.  
  142.     ; Возвести 10 в степень количества цифр
  143.     fld     [float2]
  144.     fld     [float2]
  145. @@:
  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
  160. @@:
  161.     fmulp   st1,st
  162.  
  163. loc_rounded:
  164.     ; Полученное значение меньше 1.0e16 ?
  165.     fcom    [float1]
  166.     fstsw   ax
  167.     test    ah,1
  168.     jz      @f
  169.     fmul    [float2]
  170.     dec     [digits_count]
  171. @@:
  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
  181. @@:
  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
  212. @@:
  213.     rep     movsb
  214.     mov     al,'.'
  215.     stosb
  216.     mov     ecx,10h
  217.     sub     ecx,[digits_count]
  218.  
  219. loc_fraction_filled:
  220.     rep     movsb
  221.     jmp     @f
  222.  
  223. loc_clear_fraction:
  224.     ; Удалить завершающие нули дробной части
  225.     dec     edi
  226. @@:
  227.     cmp     byte [edi-1],'0'
  228.     jz      loc_clear_fraction
  229.     cmp     byte [edi-1],'.'
  230.     jnz     @f
  231.     dec     edi
  232. @@:
  233.     jmp     loc_clear_stack
  234.  
  235. loc_mantiss_and_exponent:
  236.     ; Дробная часть мантиссы
  237.     movsb
  238.     mov     al,'.'
  239.     stosb
  240.     movsd
  241.     movsd
  242.     movsw
  243.     ; Удалить завершающие нули дробной части
  244. @@:
  245.     cmp     byte [edi-1],'0'
  246.     jne     @f
  247.     cmp     byte [edi-2],'.'
  248.     je      @f
  249.     dec     edi
  250.     jmp     @b
  251. @@:
  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
  261. @@:
  262.     stosb
  263.  
  264.     ; Значение экспоненты
  265.     mov     eax,ebx
  266.     mov     ecx,10
  267.     mov     ebx,4
  268. @@:
  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]
  280. @@:
  281.     lodsb
  282.     cmp     al,'0'
  283.     jne     @f
  284.     dec     ecx
  285.     jmp     @b
  286. @@:
  287.     dec     esi
  288.     rep     movsb
  289.  
  290. loc_clear_stack:
  291.     ; Восстановить управляющее слово
  292.     fldcw   [old_cw]
  293. loc_ret:
  294.     ; Окончание строки
  295.     mov     al,0
  296.     stosb
  297.  
  298.     ; Восстановить все регистры
  299.     popa
  300.     ret
  301.  
  302. float1  dq      1.0e16
  303. float2  dq      10.0
  304.  
  305. endp