Interpretacja liczby typu float.

0

Hey!

Tak, mam problem z językiem asemblera :D ;)

Nie potrafię zinterpretować wartości 80 bitowej 3FFE8000000000000000
Gdzie jest przecinek?

Wykonałem działanie 1/2, powinno dać 0,5... ale format tej liczby jest dla mnie niejasny...

    finit
    fild    dword [a]   ; st1
    fild    dword [b]   ; st0
    fdivp   st1     ; st1 = st1/st0
    fstp    tword [result]  ; zapisz

a       dd  1
b       dd  2
result  dt  0.0
0

https://en.wikipedia.org/wiki/Extended_precision
W dużym skrócie, w x86 float i double są kodowane zupełnie inaczej niż inty. 80 bitów podzielonych jest na 3 części: bit znaku, rząd wielkości (czyli do jakiej potęgi podnieść 2, 15 bitów) i podstawę mnożoną przez 2 do odpowiedniej potęgi. Dlatego pozwalają kodować nieporównywalnie większe i mniejsze liczby, choć czasem ze stratą dokładności.

1

Trochę na boku: nie wiem czy nie lepiej byłoby zignorować wszystkie gówniane instrukcje 8087 i użyć double 64 bitowego z SSE i rejestrów XMM.
Tak dywaguje - nie znam się, ale cały model programowania 8087, te 80 bitów to dla mnie jakaś komedia.

0

O! Znalazłem coś co w zupełności wyczerpuje moje potrzeby :) https://gist.github.com/nikAizuddin/c2d5cfad8c6abe5bd2ed

Pokazane jest jak wyciągnąć wartość za oraz przed przecinkiem

;+---------------------------------------------------------------------+
;| Get 0.12345678 from 2147483647.12345678                             |
;|                                                                     |
;| Technique used:                                                     |
;| 0.12345678 = 2147483647.12345678 - 2147483647.00000000              |
;+---------------------------------------------------------------------+

    finit                        ;initialize fpu
    fld    qword [double_sample] ;push double_sample to st1
    fild   dword [integer_part]  ;push integer_part to st0
    fsub                         ;st0 := st1 - st0
    fstp   qword [temp]          ;temporarily store subtract result

;+---------------------------------------------------------------------+
;| Convert 0.12345678 to 12345678                                      |
;|                                                                     |
;| Technique used:                                                     |
;| Multipy 0.12345678 with 8. But, if you multiply it with 7, you'll   |
;| get 7 decimal places only.                                          |
;|                                                                     |
;| If the program is set to 6 decimal places, the program will convert |
;| 0.12345678 to 123457.                                               |
;+---------------------------------------------------------------------+

    finit                         ;reset fpu
    fld    qword [temp]           ;st1 := temp
    fild   dword [decimal_places] ;st0 := decimal_places
    fmul                          ;st0 := st1 * st0
    fistp  qword [decimal_part]   ;save decimal_part
0

Działa :) (wkleiłem obrazek, bo na forum jest paskudne formatowanie tabulatorów)

0

Opakowałem wszystko w procedury https://github.com/Blackend/C[...]master/software/soler/fpu.asm
Dziękuję za poświęcony czas.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0