>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
      Práce s koprem (koprocesorem ;-)
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

      Nedávno,  dělajíce  4kb  Intro  na  Demobit  '96  (který  byl stejně
      odložen),  jsem  byl  donucen  dělat  v čistém assembleru. Což se až
      donedávna  nestalo, neboť jsem ještě nikdy nebyl limitován velikostí
      výsledného  kódu.  Takže  se do ASM přepisovaly pouze kritické části
      programů ...
      A  protože  Pasquil  i  C  se za Vás starají o práci s koprem, nikdy
      nebylo  nutno  hlavu zatěžovat tím, jak vůbec pracuje - až nedávno.
      A  při  té  časové  tísni  jsem  narazil na KATASTROF+LN- nedostatek
      jakékoliv  STRAVITELN+  informace o koprech ... vše jsem musel lovit
      ze  zdrojáků  a za použití různých helpů ...Něco málo o tom, co jsem
      vykoumal, zde přináším :

      Koprocesor   obsahuje  registry,  podobně  jako  procesor.  Má  jich
      podstatně méně, ale někdy je jejich celková kapacita větší než volné
      místo na mém HDD :-) Jedná se o datové a pomocné registry.

      Datové : je  jich  8  a každý má 80 bitů. Koprocesor  totiž  interně
               pracuje  POUZE  s  80ti  bitovými  RE+LNÝMI čísly. Pokud mu
               zadáte číslo třeba typu integer a 64bit on si ho stejně, po
               zapsání  do  jednoho  z  registrů,  převede  do  těch  80ti
               reálných  bitů  (reálných míněno ve smyslu floating-point).
               Tyto  registry  jsou  značeny  jako  ST(X),  kde X je číslo
               jednoho  z  8mi  registrů.  S  těmito  registry  se zachází
               podobně  jako  se  zásobníkem  (STACK) typu LIFO (Last In -
               First Out). To znamená že se číslo zapíše "nahoru" a ty, co
               tam  byly  před  ním,  se jakoby sesunou o 1 dolu. Registr,
               který  je  "nahoře"  (tj.  hodnota vložená jak poslední) je
               označen  jako  ST(0)  (nebo  ekvivalentně  ST)  , a ostatní
               následují za ním. Příklad:

                    ST(0)    10.3987
                    ST(1)    1.75344
                    ST(2)       ....
                        vložím číslo 22 :
                    ST(0)    22
                    ST(1)    10.3987
                    ST(2)    1.75344
                    ST(3)       ....

               Pokud   se  stane,  že  vám  "zásobník"  (=registry  ST(X))
               přetečou,  je  generována nějaká výjimka v řídícím registru
               (SF,C1).

      Pomocné : jsou 3 po 16ti bitech.

          Řídící: nastavuje parametry některých funkcí procesoru.
                  Uvedu nejdůležitější:
                bit 8 - 9 : (PC - Precision control)
                            nastavování přesnosti - pokud
                            nastavíte menší přesnost,je výpočet rychlejší.
                            Možnosti jsou následující:
                               00 :  24 bitů
                               01 :  nikde jsem nevypátral
                               10 :  53 bitů
                               11 :  64 bitů (standartně)
                bit 10-11 : (RC - Round control)
                            nastavování způsobu zaokrouhlování. Nastavení:
                               00 :  normální zaokrouhlování
                               01 :  zaokrouhlení dolů
                               10 :  zaokrouhlení nahoru
                               11 :  truncate :) čili useknutí des. části
          Stavové: něco  jako  registr (E)FLAGS u  procesoru. Odráží
                     momentální stav (psychický ;-) koprocesoru.
                bit 8,9,10,14 : tyto bity jsou nastaveny podle proběhnuvší
                                operace
                bit 11 - 13 : obsahuje  číslo registru ST,  který je právě
                              "nahoře"
                bit 6 : (SF - Stack fault).  Nastává při chybné  operaci s
                      registry ST.Buď jsme chtěli vložit více jak 8 čísel,
                      nebo jsme chtěli více jak 8 čísel vybrat.

          Doplňující: obsahuje informace obsahu o každém z 8mi ST
                    registrů (po 2 bitech). Může v něm být :
                        00 - registr je obsazen
                        11 - registr je prázdný
                        01 - v registru je nula
                        10 - v registru je nějaké speciální číslo
                             (+- nekonečno a tak ...)

      Možná,  že  si mnozí řeknou: "No jo, ale von nám zapoměl popsat tvar
      reálných  čísel".  Nezapoměl,  ale  nepopíšu je, neboť je dost dobře
      nechápu.
      Ono  je  totiž  dost dobře možné pracovat s koprem, aniž bysme tento
      tvar znali. Jak ? Za pomoci fixed-point.

      Ale napřed popíšu "pár" užitečných instrukcí koprocesoru:

      Instrukce pro práci se zásobníkem:

         FLD  : nahraje do registru ST reálné číslo v paměti (32,64,80bit)
                 ex:   Mov ST(0),  promenna
                       ; promenna muze byt DWORD,QWORD,TBYTE
         FLD1 : nahraje do registru ST hodnotu 1
         FLDPI: nacpe tam Pí
         FLDZ :   -"-     nulu
         FILD : nahraje do ST číslo typu INTEGER (16,32,64 bit)
         FST  : reálné  číslo  z  ST(0) nahraje  do proměnné a  FSTP navic
                vyjme tuto hodnotu ze zásobníku (tj. jakoby posune všechny
                zbylé o 1 nahoru)
                 ex:  Mov promena, ST(0)
                      Pop ST(0) (jen uz FSTP)
         FIST/FISTP: číslo INTEGER nahraje z  ST(0) do paměti (zkonvertuje
                jej z reálného čísla)
         FDECSTP/FINCSTP: sníží/zvýší o 1 hodnotu v bitech 11-13 stavového
                registru. Prostě se  změní číslo registru, který je nahoře
                - místo ST(2) bude "nahoře" (= v ST(0) ) třeba ST(1), nebo
                ST(3) v druhém případě.
         FFREE : vyprázdní daný registr
                  př: FFREE ST(6) ... vyprázdní 6ku ...

      Pozn :
            Instrukce  končící  na P (FISTP,FSTP,FMULP,FDIVP ...) jsou od
             svých  "nepéčkových"  ekvivalentů  rozdílné  tím, že odstraní
             hodnotu   na  vrcholu  zásobníku.  Dalo  by  se  rozložit  na
             instrukce  AKCE  a  POP.  Je to docela užitečná vlastnost ...
             Příklady níže.
            Zápis ST je ekvivalentní zápisu ST(0) - v obou případech máme
             na mysli ten registr, který je "nahoře".
            Instrukce  bez  operandu (FSQRT,FSIN,FCOS...) pracují tak, že
             nahradí hodnotu v ST hodnotou, kterou vypočítá.
                      FISTP prom  - uloží ST(0) do prom a odstraní ST(0)
                                    ze zásobníku (tj. všechny ostatní
                                    posune o 1 nahoru)
                      FMULP ST(x),ST  - udělá : ST(x)=ST(x)*ST a ST vymaže
                      FSIN            - udělá ST = sin(ST)

          Aritmetické instrukce :
         FABS
         FADD
         FCOS/FSIN/FSINCOS
         FCHS
         FPTAN/FPATAN
         FRNDINT
         FMUL/FMULP/FIMUL ...
         FDIV/FDIVP/FIDIV ...
         FSQRT
         FSUB
         FXCH
      a další ...

      Instrukce ovládání kopru :

         FINIT: nutno zavolat na začátku programu - inicializuje kopr.
         FNINIT: provede inicializaci, ale bez interní kontroly - což je
                 rychlejší
         FWAIT: je ekvivalentní instrukci WAIT
         FSAVE
         FRSTOR
         FSTENV
         FSTCW

      Teď  k té práci s koprem ... není totiž nic jednoduššího, než použít
      fixed  point. To znamená, že si do kopru hodíte nějakou hodnotu a on
      si  ji  převede (bohudíík) na reálné číslo (80bitové). Pak si můžete
      dělit, násobit, kosínovat, odmocňovat a tak ...

      Mno  a  nakonec  to  celé  vynásobíte  konstantou  tak  velkou,  aby
      zachovala všechna velká čísla a dostatek desetinných - prostě abyste
      se vešli do těch výsledných 16/32/64 bitů (vyberte si co chcete :-).
      Mno  a  pak  použijete  instrukci  FIST/FISTP  a ta to pěkně hodí do
      paměti.

      A je po práci s koprem ...

      Hodím  sem  příklad  v ASM, který slouží na předpočítání SIN tabulky
      (0-360 stupňů)...

                           Examplesák na práci s koprem


            výheň