Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm: Общие вопросы > число с плавающей точкой


Автор: alex_net_2004 22.3.2005, 14:37
Здвавствуйте всем!

Скажите пожалуйста, может кто знает, как на Assembler'e без применения языков высокого уровня вывести на экран монитора число с плаающей точкой (например 7.56). Это число получено при использовании операций сопроцессора и не является строкой с окончанием нуль.

Т. е. необходимо преобразовать полученное в результате расчётов число с плаваюшей точкой к его эквивалентному строковому значению.

Автор: Chingachguk 22.3.2005, 14:50
Код

; ***** 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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)