80 bit floats

Тема в разделе "WASM.BEGINNERS", создана пользователем edemko, 29 авг 2010.

  1. edemko

    edemko New Member

    Публикаций:
    0
    Англомовная:
    http://board.flatassembler.net/topic.php?t=11847

    Полный архив:
    http://code.google.com/p/fasmme/downloads/detail?name=80%20bit%20floats.rar&can=2&q=

    Надеюсь где-то поможет.
    Сам учил с мая 2009, было трудно.
    Код (Text):
    1. _________________________________________________________
    2. 80 bit floats - числа с плавающей запятой размером 80 бит
    3.  
    4.  
    5.  
    6.  
    7. Этот документ ни коим образом не претендует на звание путеволителя по форматам чисел.
    8. На то есть специализированные справочники, перепечатывать которые нету смысла.
    9. Все же мы постараемся пролить некий свет на целевой тип данных, с которыми оперирует
    10. FPU(сопроцессор). И так, 80 бит = десять байт = TBYTE. Именно их и рассмотрим, так
    11. как те наиболее длинные и позволяют, соответственно, разширить диапазон всевозможных
    12. значений. Любые данные на стадии загрузки автоматически переводятся именно в такую
    13. форму. Как совет, всегда ищите сходимости/аналогии между тем, что вы знаете и чего нет.
    14.  
    15.  
    16.  
    17.  
    18. Пускай в нас есть 625d чего-то.
    19.   Разложим: 6*10^2 + 2*10^1 + 5*10^0 =
    20.       = 600    + 20     + 5      =
    21.       = 625              =
    22.       = 6.25e2
    23.  
    24.  
    25.  
    26.  
    27. А чего-то есть ровно столько 0.625d.
    28.   Так, для разминки: 0*10^0 + 6*10^-1 + 2*10^-2 + 5*10^-3 =
    29.            = 0      + 0.6     + 0.02    + 0.005   =
    30.            = 0.625                =
    31.            = 6.25e-1
    32.  
    33.  
    34.  
    35.  
    36. Посмотрим, как целое 625d смотрится в двойке:
    37.   625 / 2, 1 ->        Проверим: 1*2^0 = 001 +
    38.   312 / 2, 0 ->            + 0*2^1 = 000 +
    39.   156 / 2, 0 ->            + 0*2^2 = 000 +
    40.   078 / 2, 0 ->            + 0*2^3 = 000 +
    41.   039 / 2, 1 -> остатки     + 1*2^4 = 016 +
    42.   019 / 2, 1 ->            + 1*2^5 = 032 +
    43.   009 / 2, 1 ->            + 1*2^6 = 064 +
    44.   004 / 2, 0 ->            + 0*2^7 = 000 +
    45.   002 / 2, 0 ->            + 0*2^8 = 000 +
    46.   001 / 2, 1 ->            + 1*2^9 = 512 = 625
    47.  
    48.   В случае нападения трудностей, делите 625 на 10, но переносите свойства на двоичную с-му исчисления - делите на 2:
    49.   625., для получения 5 мы делим на 10
    50.     для получения 2 мы делим на 10 на 10
    51.     для получения 6 мы делим на 10 на 10 на 10
    52.   Ну как, нок-аут, забили страх?
    53.  
    54.   = 1001110001.b * 2^0
    55.   = 100111000.1b * 2^1
    56.   = 10011100.01b * 2^2
    57.   = 1001110.001b * 2^3
    58.   = 100111.0001b * 2^4
    59.   = 10011.10001b * 2^5
    60.   = 1001.110001b * 2^6
    61.   = 100.1110001b * 2^7
    62.   = 10.01110001b * 2^8
    63.   = 1.001110001b * 2^9, fpu всегда старается представлять числа именно так - это нормализация
    64.  
    65.  
    66.  
    67.  
    68. Ура, мы знаем способ получения целой части :)%
    69. Так идемте за щебнем, 625.625d, о я о дробовой части, пардон:
    70.   625, уже известно, равно 1001110001b и, словно в десятичной, в двоичной тоже остается присоединить
    71.   дробь 0.625.
    72.  
    73.   Возвратимся к нашей нумерике:
    74.   0.625, для получения 6 умножаем на 10
    75.      для получения 2 умножаем на 10 еще на 10
    76.      для получения 5 умножаем на 10 еще на 10 и еще на 10
    77.  
    78.   только для бинарного счисления множим на 2:
    79.   0.625 * 2, 1 ->        Сверимся: 1*2^-1 = 0.500 +
    80.   0.250 * 2, 0 -> остатки         + 0*2^-2 = 0.000 +
    81.   0.500 * 2, 1 ->            + 1*2^-3 = 0.125 = 0.625
    82.  
    83.   = 0.101b * 2^0
    84.   = 1.010b * 2^-1, fpu всегда старается представлять числа именно так - это нормализация,
    85.            а числа зовут нормализированными, но не мучайте этим голову
    86.            просто следуем традиции
    87.  
    88.   Совмещаем 625.0 и 0.625.
    89.   Во-первых, упорядочим суммируемые, так как  625.0
    90.                         + 0.625 неверно.
    91.     625.0
    92.   +   0.625
    93.   = 625.625 верно.
    94.  
    95.   FPU тоже так делает(ясный день/пень/картошка), тем самым теряя драгоценную дробь, биты, хвост, остаток, звите как хотите.
    96.   Именно поэтому 80 бит - целевой формат, хотя те тоже не бесконечны.
    97.  
    98.     1001110001.000b
    99.   +      0.101b
    100.   = 1001110001.101b * 2^0
    101.   = 1.001110001101b * 2^9
    102.     положительн---отрицательные степени двух
    103.  
    104.  
    105.  
    106.  
    107. Вроде так, давайте намуляем мозоль.
    108.   Как знаете, ЧИСЛО/10=ЧИСЛО*0.1.
    109.   Че, поехали :?
    110.   0.1 * 2
    111.   -------
    112.   0.2 * 2
    113.   0.4 * 2
    114.   0.8 * 2
    115.   .......
    116.   1.6 * 2
    117.   1.2 * 2
    118.   0.4 * 2
    119.   0.8 * 2
    120.   .......
    121.   1.6 * 2
    122.  
    123.   .000(1100)b, вы догадались что это?
    124.   Примерно = .0001101b, если заокруглить. Видели, 0.1 - нескончаемая дробь.
    125.   Располагая на DWORD: .1100'1100'1100'1100'1100'1100'1100'1101 двоично   shr 3
    126.              = .c   c    c    c    c    c    c    d 16тирично shr 3
    127.  
    128.   Учтите простой принцип: 10*0.1 = 10*1.0/10.
    129.   Отсюда, для выделения целой части, нужно выполнить eax*edx shr 32+3.
    130.   32 из-за того, что .cccc'cccd CPU рассматривает, как обычное целое.
    131.   Вспоминаем принцип выше!
    132.   03 из-за того, что .cccc'cccd = 0.1 * shl 3 те умноженное на три для нормализации.
    133.  
    134.   [код]
    135.       mov     edx,$cccccccd      ;0.1 * 2^+3
    136.       mov     eax,1'234'567'890  ;делимое, любое число, даже 0
    137.       mul     edx            ;ЧИСЛО*0.1, получим 64 бит: DWORD*DWORD=QWORD
    138.       shr     edx,3          ;целое есть
    139.   [/код]
    140.  
    141.  
    142.  
    143.  
    144. Обошлись без О-всемогучего FpU, кста не правда о могучести.
    145.   В будущем, возможно, сопроцессор вам сослужит в кошелек или в уважуху, так распишем TBYTE, а то трандосим.
    146.   Зато в тему:
    147.   0'000000000000000'0.000000000000000000000000000000000000000000000000000000000000000b
    148.   | |           |
    149.   | |           |мантиса размером в 64 бит
    150.   | |
    151.   | |2-кова степень или экспонента(15 бит ее размер), умножаемая на мантису
    152.   |
    153.   |знак числа размером в бит, 1="-", 0="+"
    154.  
    155.   +0d      = 0'000000000000000'0.000000000000000000000000000000000000000000000000000000000000000b
    156.   -0d      = 1'000000000000000'0.000000000000000000000000000000000000000000000000000000000000000b
    157.  
    158.   В западло десяти, степень двух(экспонента) подкручивает счетчик своего рейтинга - и 0 = $3fff.
    159.   Следовательно -1=$3fff-1, 1=$3fff+1, и тд.
    160.   Также: FXTRACT в исполнении FPU и ему подобных, выковыривая мантису в ST0 и экспоненту в ST1, ведут себя вот так неадекватно:
    161.      $0000'8xxxxxxx'xxxxxxxx -> -16'382
    162.      $0000'4xxxxxxx'xxxxxxxx -> -16'383
    163.      обратите внимание, чему равна экспонента
    164.  
    165.   Эх, вот они:
    166.   +625.625 = 0'100000000001000'1.001110001101000000000000000000000000000000000000000000000000000b
    167.   -625.625 = 1'100000000001000'1.001110001101000000000000000000000000000000000000000000000000000b
    168.            _______________ -----____----____
    169.            $3fff+9=4008    9    c   6   8
    170.  
    171.  
    172.  
    173.  
    174. Чутка практики.
    175.   Суммируем: 625.625 + 001.000 = 626.625
    176.          разнормализируем 625.625, ссовывая число 9 раз влево, тоесть получем реальное число
    177.            1001110001.101000000000000000000000000000000000000000000000000000b
    178.          разнормализируем 001.000, ссовывая 0 раз ни влево, ни вправо
    179.             1.000000000000000000000000000000000000000000000000000000000000000b
    180.          суммируем, вспомните, как додавали 625. и .625
    181.            1001110010.101000000000000000000000000000000000000000000000000000b
    182.          нормализируем
    183.            1.001110010101000000000000000000000000000000000000000000000000000b
    184.          hex
    185.            $4008'9ca80000'00000000
    186.  
    187.   Суммируем: 625.625 + 625.625 = 1251.25
    188.          выровнять/разнормализировать оба числа за позициями комм и сложить
    189.            1001110001.101000000000000000000000000000000000000000000000000000b
    190.            1001110001.101000000000000000000000000000000000000000000000000000b
    191.           10011100011.01000000000000000000000000000000000000000000000000000b
    192.          нормализируем, подтягивая точку/комму вверх на 10 позиций
    193.          помните о балансировании: на сколько множим - на столько и делим, и наоборот, на то она и экспонента
    194.            1.001110001101000000000000000000000000000000000000000000000000000b
    195.          hex
    196.            $4009'9c680000'00000000
    197.  
    198.   Суммируем: 625.000 - 625.625 = -(625.625-625.000) = -0.625
    199.          мантисы вравновешены, нечего двигать, отнимаем
    200.            1.001110001101000000000000000000000000000000000000000000000000000b
    201.            1.001110001000000000000000000000000000000000000000000000000000000b
    202.            0.000000000101000000000000000000000000000000000000000000000000000b
    203.          нормализируем умножением на 2^10(сдвигом 10 позиций влево)
    204.            1.010000000000000000000000000000000000000000000000000000000000000b
    205.          hex
    206.            $3fff+9-10'a0000000'00000000 МЕНШЕ 0
    207.            $3ffe     'a0000000'00000000 МЕНШЕ 0
    208.            $bffe     'aaaaaaaa'00000000
    209.  
    210.   Множим:    a^x * a^y = a^(x+y) напр. 1.5*0.75 = 15*10^-1 * 75*10^-2 = 15*75*10^(-1+-2)
    211.          для понимания помучаем CPU
    212.          1.50 = 3FFF'C0000000'00000000 = 2^0  * 1.1b
    213.          0.75 = 3FFE'C0000000'00000000 = 2^-1 * 1.1b
    214.          заново просмотрите деление на десять ...
    215.          заново просмотрите умножение на 0.1 ...
    216.          хохе, вы уяснили, да нет, не "не на *беш - не проживешь", как умножать дошло :?
    217.          кстати, поговорка паршивая, никогда не дурите людей
    218.          повторимся о маневрах: 0.1*0.1 = 1*1/10/10
    219.          [код]
    220.          mov     eax,$C0000000
    221.          mov     edx,$C0000000
    222.          mul     edx
    223.          shrd    eax,edx,31*2+1-32
    224.          shr     edx,31*2+1-32    ;edx.eax = целое.дробь = 1.125
    225.                       ;результат, как целое. в edx, может стать разнормализированным
    226.                       ;дробь в EAX=$20000000 тоже
    227.                       ;та ну и пусть, главное, чтоб осмысливали процесс
    228.          [/код]
    229.  
    230.   Множим:    00.9 = 3FFE'E6666666'66666666, exp=-1
    231.          10.0 = 4002'A0000000'00000000, exp=+3
    232.          [код]
    233.          mov     eax,$E6666667
    234.          mov     edx,$a0000000
    235.          mul     edx
    236.          shr     edx,31*2+1-3-32  ;edx=9
    237.          [/код]
    238.  
    239.  
    240.  
    241.  
    242. Будет время, сходите сюда:
    243.   http://ray.masmcode.com/
    244.   http://www.intel.com/products/processor/manuals/
    245.  
    246.  
    247.  
    248.  
    249. Писалось:
    250.   2010_08_28, 10:52, время было киевское
    251.   2010_08_28, 23:00, русская версия
    252.  
    253.  
    254.  
    255.  
    256. Меня вы знаете:
    257.   edemko@rambler.ru
     
  2. edemko

    edemko New Member

    Публикаций:
    0
    Интересное форматирование получилось, писал в wink.exe(прототип fasmw.exe).
    Возможно это форум или опция фасма "Optimal fill on saving".
    В редакторе смотрелось ок.
     
  3. leo

    leo Active Member

    Публикаций:
    0
    - Эт, вряд ли - усмехнулся Сухов (C)
    Особенно интересен стиль изложения, расчитанный на разные целевые аудитории - одним "где суть", а другим - "где захотят, там и суть", а в итоге - "за двумя зайцами погонишься - ни одного не поймаешь" ;)
     
  4. edemko

    edemko New Member

    Публикаций:
    0
    [leo]
    Переводясь на физ-мат, я осозновал объемы академок, их было 10.
    Пытался до горечи учить умные книги.
    Прошол год, академки так и висели, а успехи те же.
    Меня отчислили.
    Восстановился, за 4 месяца сдал 9 штук + 2 хвоста, с сентября могут взять на госзаказ.
    Никаких взяток не давал.
    Так чего же такого начитался?
    Вы все правильно сказали.
    [/leo]

    Поделитесь примером деления tbyte.
     
  5. leo

    leo Active Member

    Публикаций:
    0
    Зачем ?! Для этого есть сопроцессор, он же FPU. А если его где-то нет, то и нефиг связываться с tbyte и вообще с плавяющей точкой - достаточно fixed
     
  6. Ustus

    Ustus New Member

    Публикаций:
    0
    edemko
    Могу сбросить исходники библиотеки floating-point для AVR. :)
    Там, правда, только 64 бита, но мало не покажется :):)
     
  7. edemko

    edemko New Member

    Публикаций:
    0
    leo, может я не прав, но мне хотелось добавить смысла в:
    http://user.cs.tu-berlin.de/~lordmaik/projects/IEEE754Converter/ieee754.htm
    http://user.cs.tu-berlin.de/~lordmaik/projects/IEEE754Converter/FloatingPointArithmeticsIEEE754Examples.pdf
    Ustus, ок
     
  8. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    leo
    одним "где суть", а другим - "где захотят, там и ссуть"
     
  9. Ustus

    Ustus New Member

    Публикаций:
    0
    edemko
    Э-э-э... вообще-то это была шутка. :)
    Но если надо - могу скинуть, только аккуратно, ибо варез.
    Уточняю еще раз. Библиотека для AVR. Atmel. RISC8. :):):) На асме :):):):) Точно надо? :)
     
  10. edemko

    edemko New Member

    Публикаций:
    0
    Ustus
    я нашел - не надо
    о)=