На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
  
> Числа с плавающей точкой , преобразовать в строку
    Уважаемые программисты! Понимаю, что тема избита, но - если ввод и преобразование числа я ещё понял, то с выводом возникли проблемы. Вот как я принимаю число:
    ExpandedWrap disabled
      format PE console
      include 'win32axp.inc'
       
      .data
      ns dd ?
      hout dd ?
      buffer db 51 dup (?)
      help db 'Usage: con_4islo.exe NUMBER',0
      Retry db 'Program fails. Please, retry',0
      num10 dt ?
      chislo dd ?
      ten dd 10
      minus db ?
      status dw ?
      to4ka dd ?
       
      .code
      fuck:
      invoke GetStdHandle,STD_OUTPUT_HANDLE
      mov [hout],eax
      invoke GetCommandLine
      mov esi,eax
      cycle1:
       cmp byte [esi],20h
       je parameter
       cmp byte [esi],0Dh
       je najobka
       inc esi
       jmp cycle1
      parameter:
       mov edi,buffer
       mov ecx,50
         cycle2:
           inc esi
           mov al,byte [esi]
           cmp al,0Dh
           je konets
           mov byte [edi],al
           inc edi
           loop cycle2
       
      konets:
      invoke lstrlen,buffer
      mov ecx,eax
      mov esi,buffer
      mov edi,esi
      add edi,ecx
      dec edi
      xor eax,eax
       
       
      finit
      fldz
      mov al,byte [esi]
      cmp al,2Dh
      je otric
      cycle3:
        mov al,byte [esi]
        inc esi
        cmp al,2Eh
        je drobnoe
        cmp al,2Ch
        je drobnoe
        sub al,30h
        jb retry
        cmp al,9
        ja retry
        mov [chislo],eax
        fild [ten]
        fmulp st1,st
        fild [chislo]
        faddp st1,st
        loop cycle3
       fldz
       jmp NoMore
       
      drobnoe:
        dec ecx
        xor eax,eax
        fldz
       cycle4:
          mov al,byte [edi]
          dec edi
          sub al,30h
          jb retry
          cmp al,9
          ja retry
          mov [chislo],eax
          fild [chislo]
          faddp
          fild [ten]
          fdivp st1,st
          loop cycle4
       
      NoMore:
        faddp st1,st
        xor eax,eax
        mov al,[minus]
        test al,al
        jz zagruz
        fchs
      zagruz:
        fstp tbyte [num10]
      exit:
      invoke ExitProcess,0
       
      najobka:
       invoke WriteConsole,[hout],help,27,ns,NULL
       
       
       
      retry:
       invoke WriteConsole,[hout],Retry,28,ns,NULL
       jmp exit
       
      otric:
      mov [minus],1
      dec ecx
      inc esi
      jmp cycle3
       
      .end fuck

    И вот, я положил число в переменную num10 типа tbyte (это BCD формат, я так понял?) - я в принципе могу грузануть её обратно в стек FPU, провести необходимые арифметические операции, но как мне преобразовать это число в строку?
    Пожалуйста, не отсылайте меня к масмовским либам, а поясните хотя бы в общих словах алгоритм разбора BCD. Я, наверное, сам смогу вывести цифры в строку, но как определить десятичный порядок и правильно поставить разделитель-точку?
    Прошу вашей помощи
      Цитата adrax @
      положил число в переменную num10 типа tbyte (это BCD формат, я так понял?)

      TBYTE - это не обязательно BCD ;) Это просто 10-ть байт :) А уж как ты их будешь трактовать в программе, чисто твое дело.
      Цитата adrax @
      но как определить десятичный порядок и правильно поставить разделитель-точку?

      Ничего определять не надо. Точка будет там, где ты этого захочешь.
      Попробую объяснить на самом простом (и быстром) способе - табличном.
      Ну во первых известно, что после запятой может быть от 0 до 17 знаков. Вот и заведи таблицу:
      ExpandedWrap disabled
        ; 10 в степени N
        tenexp:
          dq 1.0E1, 1.0E2, 1.0E3, 1.0E4, 1.0E5, 1.0E6, 1.0E7, 1.0E8
          dq 1.0E9, 1.0E10, 1.0E11, 1.0E12, 1.0E13, 1.0E14, 1.0E15, 1.0E16
          dq 1.0E17

      Т.е. массив состоит из заранее вычисленных коэффициентов 10 в степени от 1 до 17.
      Во вторых, поскольку при сохранении числа со стека сопроцессора в BCD происходит округление до целого, то прежде чем сохранять, его нужно масштабировать. А если по русски, то, к примеру, есть число 2222,3334444. Тебе нужно вывести его на экран (или куда там еще :-) в виде: 2222,333. Но поскольку при сохранении в BCD ты получишь число 2222, то необходимо еще до сохранения преобразовать его к виду 2222333,444. Это можно сделать умножив исходное число на 10^3 (поскольку нужно 3 числа после запятой, то и степень будет равна 3). Вот здесь то и пригодится массив tenexp :yes: А дальше при преобразовании BCD в строку просто вставляешь точку там где ее и заказывали. И все.
      Пробуй, если не получится - поможем :)
        Цитата adrax @
        положил число в переменную num10 типа tbyte (это BCD формат, я так понял?)

        Смотря как "положил" :D
        fstp tbyte [num10] - сохраняет число в двоичном extended формате с плав.точкой
        fbstp tbyte [num10] - округляет число до целого и сохраняет в упакованном BCD-формате
        В первых (младших) 9 байтах хранятся 2*9=18 десятичных цифр числа - по 4 бита на цифру. Старший (знаковый) бит 10-го байта хранит знак числа.
        Для преобразования числа в строку с фикс.числом знаков после запятой нужно, как уже сказал AndNot, сначала умножить число на степень 10 в соответствии с требуемым числом знаков и выгрузить в BCD, а затем "ковыряться" с разбором этого BCD и формированием строки с учетом отбрасывания лидирующих нулей целой части и вставки разделительной точки на нужную позицию

        Цитата AndNot @
        Точка будет там, где ты этого захочешь
        после запятой может быть от 0 до 17 знаков

        Не совсем так. Общее число знаков целой и дробной части не может быть больше 18-ти, иначе получишь переполнение. Поэтому если предварительно не анализировать порядок числа, то задавать большое число знаков после запятой не стоит ;)
          Цитата leo @
          Поэтому если предварительно не анализировать порядок числа, то задавать большое число знаков после запятой не стоит

          Это уже тонкости, и остается только добавить, что если не получается вывести в формате с плавающей точкой, то можно попытаться вывести в научной форме. Но там немного посложнее.
            Дело в том, что если выводить в экспоненциальном (научном формате), то я могу просто тупо перебить кусок готового кода, но меня интересует именно вывод в привычном виде - с точкой (ну или запятой)

            leo
            Точно! Я ж не в BCD, я ж в extended!! Хотя всё равно не понимаю - как мне проанализировать тип extended, чтобы определить десятичный порядок и правильно пихнуть запятую... sprintf с %e не предлагайте, пжлст, лучше дайте пошаговое описание разбора extended-числа (про BCD нашёл статью "Арифметика с плавающей точкой", там рассказывается в формулах, и реализацию просто сделать на любом языке) - каков алгоритм?
              adrax, при выводе на экран и используют промежуточную BCD форму. А если extended напрямую анализировать, то сложность кода возрастет на порядок. Тебе это надо?
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0331 ]   [ 16 queries used ]   [ Generated: 13.05.25, 09:59 GMT ]