Subversion Repositories Kolibri OS

Rev

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

  1. ;
  2. ; функции для работы с числами float
  3. ;
  4.  
  5. ; Количество знаков числа после запятой (1-17)
  6. NumberSymbolsAD DW 5
  7. ; Константы (10 в степени N)
  8. MConst DQ 1.0E1,1.0E2,1.0E3,1.0E4,1.0E5
  9.        DQ 1.0E6,1.0E7,1.0E8,1.0E9,1.0E10
  10.        DQ 1.0E11,1.0E12,1.0E13,1.0E14,1.0E15
  11.        DQ 1.0E16,1.0E17,1.0E18,1.0E19,1.0E20
  12.        DQ 1.0E21,1.0E22,1.0E23,1.0E24,1.0E25
  13.        DQ 1.0E26,1.0E27,1.0E28,1.0E29,1.0E30
  14.        DQ 1.0E31,1.0E32,1.0E33,1.0E34,1.0E35
  15.        DQ 1.0E36,1.0E37,1.0E38,1.0E39,1.0E40
  16.        DQ 1.0E41,1.0E42,1.0E43,1.0E44,1.0E45
  17.        DQ 1.0E46,1.0E47,1.0E48,1.0E49,1.0E50
  18.        DQ 1.0E51,1.0E52,1.0E53,1.0E54,1.0E55
  19.        DQ 1.0E56,1.0E57,1.0E58,1.0E59,1.0E60
  20.        DQ 1.0E61,1.0E62,1.0E63,1.0E64,1.0E65
  21.        DQ 1.0E66,1.0E67,1.0E68,1.0E69,1.0E70
  22.        DQ 1.0E71,1.0E72,1.0E73,1.0E74,1.0E75
  23.        DQ 1.0E76,1.0E77,1.0E78,1.0E79,1.0E80
  24.        DQ 1.0E81,1.0E82,1.0E83,1.0E84,1.0E85
  25.        DQ 1.0E86,1.0E87,1.0E88,1.0E89,1.0E90
  26.        DQ 1.0E91,1.0E92,1.0E93,1.0E94,1.0E95
  27.        DQ 1.0E96,1.0E97,1.0E98,1.0E99,1.0E100
  28.        DQ 1.0E101,1.0E102,1.0E103,1.0E104,1.0E105
  29.        DQ 1.0E106,1.0E107,1.0E108,1.0E109,1.0E110
  30.        DQ 1.0E111,1.0E112,1.0E113,1.0E114,1.0E115
  31.        DQ 1.0E116,1.0E117,1.0E118,1.0E119,1.0E120
  32.        DQ 1.0E121,1.0E122,1.0E123,1.0E124,1.0E125
  33.        DQ 1.0E126,1.0E127,1.0E128
  34. ; Число с плавающей запятой двойной точности
  35. Data_Double   DQ ?
  36. ; Число в BCD-формате
  37. Data_BCD      DT ?
  38. ; Вспомогательный флаг
  39. Data_Flag     DB ?
  40. ; Знак результата (если не 0 - отрицательное число)
  41. Data_Sign     DB ?
  42.  
  43.  
  44. db 0 ;указатель на сдвиг в памяти
  45. ; Строка для хранения числа в коде ASCII
  46. Data_String   DB 32 DUP (?)
  47.  
  48.  
  49.  
  50. ;*******************************************************
  51. ;*  ПРЕОБРАЗОВАНИЕ ЧИСЛА С ПЛАВАЮЩЕЙ ЗАПЯТОЙ В СТРОКУ  *
  52. ;* Число имеет формат с удвоенной точностью, результат *
  53. ;* выдается в десятичном коде, в "бытовом" формате с   *
  54. ;* фиксированным количеством знаков после запятой.     *
  55. ;* Входные параметры:                                  *
  56. ;* Data_Double - преобразуемое число;                  *
  57. ;* NumberSymbolsAD - количество знаков после           *
  58. ;*                   запятой (0-17).                   *
  59. ;* Выходные параметры:                                 *
  60. ;* Data_String - строка-результат.                     *
  61. ;*******************************************************
  62. DoubleFloat_to_String:
  63.         pushad
  64.         ; Результат записывать в строку Data_String
  65.         mov     EDI, Data_String
  66.  
  67.         ; Сдвигаем число влево на NumberSymbolsAD
  68.         ; десятичных разрядов
  69.         fninit                 ;сброс сопроцессора
  70.         fld     [Data_Double]  ;загрузить число
  71.         xor ebx,ebx
  72.         mov     BX,[NumberSymbolsAD]
  73.         cmp     BX, 0
  74.         je      .NoShifts     ;нет цифр после запятой
  75.         jl      .Error        ;ошибка
  76.         dec     BX
  77.         shl     BX, 3           ;умножаем на 8
  78.         add     EBX, MConst
  79.         fmul    qword [EBX] ;умножить на константу
  80. .NoShifts:
  81.         ; Извлечь число в коде BCD
  82.         fbstp   [Data_BCD]
  83. ; Проверить результат на переполнение
  84.         mov     AX,word [Data_BCD + 8]
  85.         cmp     AX,0FFFFh  ;"десятичное" переполнение?
  86.         je      .Overflow
  87. ; Выделить знак числа и записать его в ASCII-коде
  88.         mov     AL, byte [Data_BCD + 9]
  89.         and     AL,AL
  90.         jz      .NoSign
  91.         mov     AL,'-'
  92.         stosb
  93. .NoSign:
  94. ; Распаковать число в код ASCII
  95.         mov     ebx,8    ;смещение последней пары цифр
  96.         mov     ecx,9    ;счетчик пар цифр
  97.         ; Определить позицию десятичной точки в числе
  98.         mov     DX,18
  99.         sub     DX,[NumberSymbolsAD]
  100.         js      .Error  ;ошибка, если отрицательная
  101.         jz      .Error  ;или нулевая позиция
  102. .NextPair:
  103.         ; Загрузить очередную пару разрядов
  104.         mov     AL, byte [ebx + Data_BCD]
  105.         mov     AH,AL
  106.         ; Выделить, перевести в ASCII и
  107.         ; сохранить старшую тетраду
  108.         shr     AL,4
  109.         add     AL,'0'
  110.         stosb
  111.         dec     DX
  112.         jnz     .N0
  113.         mov     AL,'.'
  114.         stosb
  115. .N0:   ; Выделить, перевести в ASCII и
  116.         ; сохранить младшую тетраду
  117.         mov     AL,AH
  118.         and     AL,0Fh
  119.         add     AL,'0'
  120.         stosb
  121.         dec     DX
  122.         jnz     .N1
  123.         mov     AL,'.'
  124.         stosb
  125. .N1:
  126.         dec  BX
  127.         loop .NextPair
  128.         mov  AL,0
  129.         stosb
  130.  
  131. ; Убрать незначащие нули слева
  132.         mov     EDI, Data_String
  133.         mov     ESI, Data_String
  134.         ; Пропустить знак числа, если он есть
  135.         cmp     byte [ESI],'-'
  136.         jne     .N2
  137.         inc     ESI
  138.         inc     EDI
  139. .N2:   ; Загрузить в счетчик цикла количество разрядов
  140.         ; числа плюс 1 (байт десятичной точки)
  141.         mov     ecx,18+1+1
  142.         ; Пропустить незначащие нули
  143. .N3:
  144.         cmp byte [ESI],'0'
  145.         jne .N4
  146.         cmp byte [ESI+1],'.'
  147.         je .N4
  148.         inc ESI
  149.         loop .N3
  150.         ; Ошибка - нет значащих цифр
  151.         jmp     .Error
  152. ; Скопировать значащую часть числа в начало строки
  153. .N4:    rep movsb
  154.         jmp    .End
  155.  
  156. ; Ошибка
  157. .Error:
  158.         mov     AL,'E'
  159.         stosb
  160.         mov     AL,'R'
  161.         stosb
  162.         mov     AL,'R'
  163.         stosb
  164.         xor     AL,AL
  165.         stosb
  166.         jmp     .End
  167. ; Переполнение разрядной сетки
  168. .Overflow:
  169.         mov     AL,'#'
  170.         stosb
  171.         xor     AL,AL
  172.         stosb
  173. ; Конец процедуры
  174. .End:
  175.         popad
  176.         ret
  177.  
  178. ;****************************************************
  179. ;* ПРЕОБРАЗОВАТЬ СТРОКУ В ЧИСЛО С ПЛАВАЮЩЕЙ ЗАПЯТОЙ *
  180. ;*      (число имеет обычный, "бытовой" формат)     *
  181. ;* Входные параметры:                               *
  182. ;* Data_String - число в коде ASCII.                *
  183. ;* Выходные параметры:                              *
  184. ;* Data_Double - число в двоичном коде.             *
  185. ;****************************************************
  186. String_to_DoubleFloat:
  187.         pushad
  188.         cld
  189.         ; Очищаем Data_BCD
  190.         mov dword [Data_BCD],0
  191.         mov dword [Data_BCD+4],0
  192.         mov  word [Data_BCD+8],0
  193.         ; Очищаем байт знака
  194.         mov     [Data_Sign],0
  195.         ; Заносим в SI указатель на строку
  196.         mov     ESI, Data_String
  197.         ; Пропускаем пробелы перед числом
  198.         mov     ecx,64 ;защита от зацикливания
  199. .ShiftIgnore:
  200.         lodsb
  201.         cmp     AL,' '
  202.         jne     .ShiftIgnoreEnd
  203.         loop    .ShiftIgnore
  204.         jmp     .Error
  205. .ShiftIgnoreEnd:
  206.         ; Проверяем знак числа
  207.         cmp     AL,'-'
  208.         jne     .Positive
  209.         mov     [Data_Sign],80h
  210.         lodsb
  211. .Positive:
  212.         mov     [Data_Flag],0 ;признак наличия точки
  213.         mov     DX,0          ;позиция точки
  214.         mov     ecx,18        ;макс. число разрядов
  215. .ASCIItoBCDConversion:
  216.         cmp     AL,'.'        ;точка?
  217.         jne     .NotDot
  218.         cmp     [Data_Flag],0 ;точка не встречалась?
  219.         jne     .Error
  220.         mov     [Data_Flag],1
  221.         lodsb
  222.         cmp     AL,0          ;конец строки?
  223.         jne     .NotDot
  224.         jmp     .ASCIItoBCDConversionEnd
  225. .NotDot:
  226.         ; Увеличить на 1 значение позиции точки,
  227.         ; если она еще не встречалась
  228.         cmp     [Data_Flag],0
  229.         jnz     .Figures
  230.         inc     DX
  231. .Figures:
  232.         ; Символы числа должны быть цифрами
  233.         cmp     AL,'0'
  234.         jb      .Error
  235.         cmp     AL,'9'
  236.         ja      .Error
  237.         ; Пишем очередную цифру в младшую тетраду BCD
  238.         and     AL,0Fh
  239.         or      byte [Data_BCD],AL
  240.         ; Проверка на конец строки
  241.         cmp     byte [ESI],0
  242.         je      .ASCIItoBCDConversionEnd
  243.         ; Сдвигаем BCD на 4 разряда влево
  244.         ; (сдвигаем старшие 2 байта)
  245.         mov     AX,word [Data_BCD+6]
  246.         shld    word [Data_BCD+8],AX,4
  247.         ; (сдвигаем средние 4 байта)
  248.         mov     EAX, dword [Data_BCD]
  249.         shld    dword [Data_BCD+4],EAX,4
  250.         ; (сдвигаем младшие 4 байта)
  251.         shl     dword [Data_BCD],4
  252.         ; Загружаем следующий символ в AL
  253.         lodsb
  254.         loop    .ASCIItoBCDConversion
  255.         ; Если 19-й символ не 0 и не точка,
  256.         ; то ошибка переполнения
  257.         cmp     AL,'.'
  258.         jne     .NotDot2
  259.         inc     ecx
  260.         lodsb
  261. .NotDot2:
  262.         cmp     AL,0
  263.         jne     .Error ;переполнение разрядной сетки
  264.  
  265. ; ПРЕОБРАЗОВАТЬ ЧИСЛО ИЗ КОДА BCD В ВЕЩЕСТВЕННОЕ ЧИСЛО
  266. .ASCIItoBCDConversionEnd:
  267.         ; Вписать знак в старший байт
  268.         mov     AL,[Data_Sign]
  269.         mov     byte [Data_BCD+9],AL
  270.         ; Сбросить регистры сопроцессора
  271.         fninit
  272.         ; Загрузить в сопроцессор число в BCD-формате
  273.         fbld    [Data_BCD]
  274.         ; Вычислить номер делителя
  275.         mov     EBX,18+1
  276.         sub     BX,CX
  277.         sub     BX,DX
  278.         cmp     EBX,0
  279.         je      .NoDiv
  280.         dec     EBX
  281.         shl     EBX,3           ;умножаем на 8
  282.         add     EBX, MConst
  283.         fdiv    qword [EBX] ;разделить на константу
  284. .NoDiv:; Выгрузить число в двоичном формате
  285.         fstp    [Data_Double]
  286.         jmp     .End
  287.  
  288. .Error:; При любой ошибке обнулить результат
  289.         fldz    ;занести ноль с стек сопроцессора
  290.         fstp    [Data_Double]
  291. .End:
  292.         popad
  293.         ret
  294.  
  295. align 4
  296. proc str_cat, str1:dword, str2:dword
  297.         push eax ecx edi esi
  298.         mov esi,dword[str2]
  299.         stdcall str_len,esi
  300.         mov ecx,eax
  301.         inc ecx
  302.         mov edi,dword[str1]
  303.         stdcall str_len,edi
  304.         add edi,eax
  305.         cld
  306.         repne movsb
  307.         pop esi edi ecx eax
  308.         ret
  309. endp
  310.  
  311. ;output:
  312. ; eax = strlen
  313. align 4
  314. proc str_len, str1:dword
  315.         mov eax,[str1]
  316.         @@:
  317.                 cmp byte[eax],0
  318.                 je @f
  319.                 inc eax
  320.                 jmp @b
  321.         @@:
  322.         sub eax,[str1]
  323.         ret
  324. endp