f2xm1

Тема в разделе "WASM.A&O", создана пользователем edemko, 9 авг 2010.

  1. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Здорово.

    Подглядывая за сорсами фасма и до(пере)делывая программу конвертации чисел(без нее мне плохо в голове вертеть), заинтересовался делением через умножение и работой без FPU(фасм щитает без него).

    Подражание фасму удалось, заместить деление умножением тоже.
    Процедура <bsa_a2f> работает опционально в FPU-режиме, когда 10^x ищем за формулой; и без FPU, циклически умножая результат на 10 или на 0.1 соответственно.
    Но это медленно, хотелось тоже через формулу, используемую в <power10>.
    Постает вопрос: как получить 2^дробь.
    Рузультат, напомню, будет = (1;2).

    Тема эта мне, как и многим, будет полезна, поэтому ложу ссылки.
    Прошу ДАДАДА прощения, но тексты не русские.
    Также выложено программу-конвертер и сорс для заинтересовавшихся/нужденных.

    Исполнительный файл и тексты интерфейса:
    http://board.flatassembler.net/download.php?id=5106
    Тексты вызываемых функций, там и float-процедуры:
    http://board.flatassembler.net/download.php?id=5043
    Теория, как делить, умножая, и доп. тулза(web-script) от неизвестного мне автора
    http://board.flatassembler.net/topic.php?p=114917#114917
    Теория на русском(не много), смотрите длинный комментарий поста #16:
    http://wasm.ru/forum/viewtopic.php?id=26577

    aggro, туда(#16) постил в целях быстрого поиска жуков и только, ну и в целях примирения с форумом, видь я сука был. В обновленном файле доделаные лежат.

    Ну вот, приветствую, спасибо и добро пожаловать.
    06:01, утро, мог напутать
     
  2. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Хороший сайт, в низу эмуляторы FPU:
    http://www.fdd5-25.net/emulators.php

    редактировал и прицепил файлик
     
  3. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
  4. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
  5. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
  6. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    редактировал: не то
     
  7. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    [​IMG]


    Можно кнопку предпросмотра в режиме быстрого редактирования?
     
  8. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
  9. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Ссылка сюда лежит на другом форуме, e-mail'ах, потому комментировал одным языком.
    10^простите, я НЕ специально.
    Ок, привет!
    Процедура еще не умеет подносить в отрицательную степень: мне нужно научиться делить.
    Прогортайте до .solve_result - там стоит "hlt".
    Как умны камни.
    Древние давно знали это.)
    Понимаю одного человека, который праду говорил, что все комментарии не влезут, и я школота. Хохохо, здоров був!
    Много не тестировал, мне трудно.
    Код (Text):
    1.         mov     eax,dword[f]
    2.         mov     ebx,dword[f+4]
    3.         mov     cx,word[f+8]
    4.         call    f2xm0
    5.         push    ecx ebx eax
    6.         fld     tbyte[esp]
    7.         add     esp,12
    8.         ret
    9. f dt 0.51
    10. ;f: dd $ffff'ffff,$ffff'ffff,$0000'3ffe
    11.  
    12.  
    13.  
    14.  
    15.  
    16.  
    17.  
    18.  
    19.  
    20.  
    21.  
    22.  
    23.  
    24.  
    25.  
    26.  
    27.  
    28.  
    29.  
    30.  
    31.  
    32.  
    33.  
    34.  
    35.  
    36.  
    37.  
    38.  
    39.  
    40.  
    41.  
    42.  
    43.  
    44.  
    45.  
    46.  
    47.  
    48.  
    49.  
    50.  
    51.  
    52.  
    53.  
    54.  
    55.  
    56.  
    57.  
    58.  
    59.  
    60.  
    61. ; IT MUST BE TESTED
    62. ; -1.0..+1.0  -> ecx:ebx:eax
    63. ; ecx:ebx:eax <- +0.5..+2.0 <- 2^ecx:ebx:eax <-no fpu
    64. ; flags.cf    <- error
    65. proc f2xm0
    66.                                       ;before you start: make sure you know fpu-nums and understand the graph
    67.         push    edx                   ;modified regs here
    68.         stc                           ;error=1
    69.         pushf
    70.  
    71.         shl     ecx,1                 ;blow-out sign bit...
    72.         shr     cx,1                  ;...to operate easy
    73.         jz      .0?                   ;try returning 2^0=1
    74.         sub     cx,$3fff
    75.         je      .1?                   ;try returning 2^-1=0.5 or 2^1=2
    76.         ja      .nok                  ;value must be within -1.0..+1.0
    77.         test    ebx,ebx
    78.         jns     .nok                  ;wrong format
    79.  
    80.         push    ecx                   ;keep value's sign in bit 16; keep current exponent
    81.         cmp     cx,$ffff
    82.         jne     .x_less_0.5           ;method<0.5, remember the picture/graph, we are under 0.5
    83.         sub     ebx,$8000'0000        ;method>=0.5, remember the picture
    84.         jnz     @f                    ;not 0.5 = const
    85.         test    eax,eax
    86.         jz      .1.4142135623730950480;0.5=const
    87.         xchg    ebx,eax               ;partially normalize
    88.         mov     word[esp],-33         ;=-1-32, exponent updated
    89. @@:     bsr     ecx,ebx               ;continue normalization process
    90.         neg     ecx
    91.         add     ecx,31                ;times to shift left
    92.         sub     [esp],cx              ;keep exponent balance
    93.         shld    ebx,eax,cl
    94.         shl     eax,cl                ;normalization finished
    95.                    ;$0000'3FFF=0      ;magic=1.1715728752538099310
    96.         mov     edx,$95F6'1998
    97.         mov     ecx,$0C43'3800
    98.         call    .mul
    99.         inc     ecx                   ;compare with another "magic"
    100.         pop     edx                   ;restore old exponent
    101.         add     cx,dx                 ;multiplication finished: values multiplied & exponents summed
    102.         neg     cx                    ;1 and more=const
    103.         cmp     cx,63
    104.         jna     @f                    ;near 0.0, so finish mode>=0.5
    105.         jmp     .1.414213562373095048_
    106. .1.4142135623730950480:
    107.         pop     edx
    108. .1.414213562373095048_:
    109.         mov     ecx,$0000'3FFF
    110.         mov     ebx,$B504'F333
    111.         mov     eax,$F9DE'647D
    112.         jmp     .solve_result
    113. @@:     shrd    eax,ebx,cl            ;getting real non-normalized result to sum it with 1.4142135623730950480 <- magic #3, remember the picture
    114.         shr     ebx,cl
    115.         xor     ecx,ecx
    116.         add     eax,$F9DE'647D        ;magic #3
    117.         adc     ebx,$B504'F333        ;remember the picture
    118.         adc     ecx,0                 ;ecx<2=const
    119.         shrd    eax,ebx,cl
    120.         shrd    ebx,ecx,cl            ;normalization finished
    121.         add     ecx,$0000'3fff        ;valid float got
    122.         jmp     .solve_result
    123. .x_less_0.5:       ;$0000'3FFE=-1     ;magic=0.8284271247461900689
    124.         mov     edx,$D413'CCCF
    125.         mov     ecx,$E779'9000
    126.         call    .mul                  ;x*magic, exponent adjusting comes then
    127.         pop     edx                   ;restore old exponent
    128.         add     cx,dx                 ;hint: when we multiply mantissas, exponents must be summed :)
    129.         neg     cx                    ;cx=2 and more=constant
    130.         cmp     cx,$003f
    131.         ja      .1                    ;to get actual value, we must shift it right more than 63 times ie. adding 1.0 to it will bring 1.0 anyway as there are no so many bits defines by the floating standard
    132.         cmp     cx,$001f
    133.         jna     @f                    ;shift count < 32
    134.         mov     eax,ebx
    135.         xor     ebx,ebx
    136.         sub     cl,$20                ;so many times left to shift right
    137. @@:     shrd    eax,ebx,cl
    138.         shr     ebx,cl
    139.         bts     ebx,31                ;add 1.0 :), so easy
    140.         mov     ecx,$0000'3fff        ;1.xxx=const
    141. .solve_result:
    142.         bt      edx,16
    143.         jnc     .ok                   ;x positive
    144.         hlt
    145.  
    146. .1?:    cmp     ebx,$8000'0000
    147.         jne     .nok                  ;wrong format
    148.         test    eax,eax
    149.         jnz     .nok                  ;wrong format
    150.         bt      ecx,16
    151.         mov     ecx,$0000'4000
    152.         jnc     .ok                   ;2^1=2
    153.         mov     ecx,$0000'3ffe
    154.         jmp     .ok                   ;2^-1=0.5
    155.  
    156. .0?:    or      ebx,eax
    157.         jnz     .nok                  ;wrong format
    158.         mov     ecx,$0000'3fff        ;exponent=0
    159.         bts     ebx,31                ;mantissa=1
    160.         jmp     .ok                   ;2^0*1=1
    161.  
    162. .1:     mov     ecx,$0000'3fff        ;exponent=0
    163.         mov     ebx,$8000'0000        ;mantissa=1...
    164.         xor     eax,eax               ;... -> 2^0*1=1
    165.  
    166. .ok:    dec     byte[esp]             ;error=0
    167. .nok:   popf
    168.         pop     edx
    169.         ret     0                     ;hi Tomasz!
    170.  
    171. .mul:   call    _64mul64
    172.         mov     eax,ecx               ;in both modes(before 0.5 and after) bit 128 may be zero - normalize
    173.         bsr     ecx,edx
    174.         neg     ecx
    175.         add     ecx,31                ;times to shift left
    176.         shld    edx,eax,cl
    177.         shld    eax,ebx,cl
    178.         mov     ebx,edx               ;ebx:eax=valid float
    179.         neg     ecx                   ;to keep exponent balance
    180.         ret     0
    181. endp
    182.  
    183.  
    184.  
    185.  
    186. ;you may skip it though it's interesting
    187. ; $ffffffff(edx)ffffffff(ecx) * $ffffffff(ebx)ffffffff(eax)      =
    188. ;=$ffffffff'ffffffff * $1'00000000'00000000 - $ffffffff'ffffffff =
    189. ;=$ffffffff'ffffffff'00000000'00000000      - $ffffffff'ffffffff =
    190. ;=$ffffffff'ffffffff'00000000'00000000  - 1 - $ffffffff'fffffffe =
    191. ;=$ffffffff'fffffffe'ffffffff'ffffffff      - $ffffffff'fffffffe =
    192. ;=$ffffffff'fffffffe'00000000'00000001, 128 bits :b
    193.  
    194. ;edx:ecx:ebx:eax = edx:ecx*ebx:eax = ecx*ebx:eax+(edx*ebx:eax)shl 32
    195. ;flags           = ?
    196. proc _64mul64
    197.         push    eax ebx edx
    198.         call    _64mul32
    199.         xchg    eax,[esp+8]
    200.         xchg    ebx,[esp+4]
    201.         xchg    ecx,[esp]
    202.         call    _64mul32
    203.         mov     edx,ecx
    204.         mov     ecx,ebx
    205.         mov     ebx,eax
    206.         pop     eax
    207.         add     ecx,eax
    208.         adc     edx,0
    209.         pop     eax
    210.         add     ebx,eax
    211.         adc     ecx,0
    212.         adc     edx,0
    213.         pop     eax
    214.         ret     0
    215. endp
    216.  
    217.  
    218.  
    219.  
    220. ;ecx:ebx:eax = ecx*ebx:eax = ecx*ebx:0+ecx*0:eax
    221. ;edx         = ?, ecx*0:eax shr 32 actually
    222. ;flags       = ?
    223. proc _64mul32
    224.         xchg    eax,ebx
    225.         mul     ecx
    226.         xchg    ebx,eax
    227.         xchg    ecx,edx
    228.         mul     edx
    229.         add     ebx,edx
    230.         adc     ecx,0
    231.         ret     0
    232. endp
     
  10. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Разбивая на больше частей, можно не делить там, где hlt.
    ...
    Лучьше циклить: f2xm1 не очень точный даже в исполнении железа.
    В наше время такой подход тупой, точный, иногда полезный, конец, спасибо.
    murder, в каком-то коде от тебя видел другую константу дл яделения на десятку, но та не всегда срабатывает, AMD тоже об том говорит. Надеюсь, с вами все ок, пропал куда-то.

    Код (Text):
    1. ;Умножить мантису TBYTE-float на 0.1 или 10 соответсвтенно.
    2. ;Процедура писалась под цикл, потому не проверяет, нормализировано ли число, иль не равно оно нулю.
    3. ;Делайте то сами лучьше раз и не посылайте проке таких чисел.
    4. ;  мантиса -> ebx:eax
    5. ;  ebx:eax <- нормализированный результат/мантиса
    6. ;  ecx     <- суммируйте с изначальной степенью числа для оплучения окончательного результата
    7. ;  flags   <- ?
    8. ;пример: mov     esi,$0000'400e
    9. ;        mov     ebx,$ffff'0000
    10. ;        mov     eax,$0000'0000
    11. ;        push    esi ebx eax
    12. ;        fld     tbyte[esp]
    13. ;
    14. ;        call    fp_div
    15. ;        add     esi,ecx
    16. ;        push    esi ebx eax
    17. ;        fld     tbyte[esp]
    18. ;
    19. ;        call    fp_mul
    20. ;        add     esi,ecx
    21. ;        push    esi ebx eax
    22. ;        fld     tbyte[esp]
    23. ;
    24. ;        add     esp,12*3
    25. proc fp_div
    26.         push    edx               ;его меняем
    27.                    ;$0000'3ffb=-4 ;это и есть 0.1
    28.         mov     edx,$cccc'cccc
    29.         mov     ecx,$cccc'cccd
    30.         call    _64mul64         ;sizeof.integer=1..2 бит, sizeof.fraction=126 бит
    31.         mov     eax,ecx
    32.         bsr     ecx,edx
    33.         neg     ecx
    34.         add     ecx,31           ;0..1
    35.         shld    edx,eax,cl
    36.         shld    eax,ebx,cl       ;float нормализировали
    37.         mov     ebx,edx          ;результат готов
    38.         pop     edx
    39.         neg     ecx
    40.         add     ecx,-4+1         ;^умножая, степени суммируют^; +1 так как sizeof.integer=1..2, а в нормализированном числе sizeof.integer=1
    41.         ret     0
    42. endp
    43. proc fp_mul
    44.         push    edx              ;предохраняйтесь Ж)
    45.         mov     edx,$a0000000    ;10.0 = $4002'a0000000'00000000, пок. спенени два = 3: 1.010b
    46.         xor     ecx,ecx
    47.         call    _64mul64         ;то само
    48.         mov     eax,ecx
    49.         bsr     ecx,edx
    50.         neg     ecx
    51.         add     ecx,31           ;то само
    52.         shld    edx,eax,cl
    53.         shld    eax,ebx,cl
    54.         mov     ebx,edx
    55.         pop     edx
    56.         neg     ecx
    57.         add     ecx,3+1          ;+3 - вспомните 10.0; +1 - представьте, что ecx=-1
    58.         ret     0                ;ИЛИ: "для получения человеческого числа нужно кому переместить на 3 позиции вправо, если нормализация не проводилась - еще раз вправо"
    59. endp                             ;здорово Clerk, комментарии не влазят :)
     
  11. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Паршивая скорость Internet, пробую прицепить сорсе эмулятора FPU.