A koprocesszor -mint neve is mutatja- matematikai társprocesszor, amit arra fejlesztettek ki, hogy nagypontosságú számokkal is tudjanak a programozók viszonylag egyszerűen számolni. Az első dolog, amit feltétlenül meg kell jegyezni a kooprocesszorról, hogy STACK-es felépítésű, és nincsenek olyan regiszterei, mint a CPU-nak, hanem veremszerkezetben tárol, 8 regiszter van: ST(0)..ST(7). Ezt legjobban a TD-vel lehet megfigyelni, s ugyanaz érvényes rá, amit a STACK-es fejezetben leirtam [IV/a]. A második fontos dolog, hogy a koproci regisztereibe NEM LEHET közvetlenül értéket adni, csak úgy ha, egy változónak értéket adsz, és azt egy utasítás lenyomja a koproci vermébe. Ugyanígy csak változóba lehet a koproci értékeit visszaszedni. Ha egy értéket lenyomsz a verembe, akkor az a vermet lejjebb tolja .

Az eredeti leirás a TASM-hoz készült, de kiderült, hogy a NASM egy picikét másképp műxik :)

Míg TASM esetén a koprocesszor regiszterek st(0)..st(7), addíg NASM esetén st0..st7!

Az első utasítás az FLD lenne. Ez a megfelelője a mov utasitásnak, de nem győzöm hangsúlyozni, hogy NEM lehet közvetlenül regisztert megadni !
 

Utasítás Jelentés
FLD ST(i) push, ST(0) <= ST(i) az ST(0)-ba másolja az ST(i) regiszter értékét
FLD mem10r push, ST(0) <= mem10r
FLD mem4r push, ST(0) <= mem4r
FLD mem8r push, ST(0) <= mem8r
FLD mem2i push, ST(0) <= mem2i
FLD mem4i push, ST(0) <= mem4i
FLD mem8i push, ST(0) <= mem8i
FLD mem10d push, ST(0) <= mem10d

Akkor lássuk, hogy mit jelentenek ezek a memXXX-ek ...
 

Utasítás Jelentés
ST(i) a lebegőpontos verem i. eleme
mem10r a memóriában tárol 10 byte-os lebegőpontos szám
mem8r a memóriában tárol 8 byte-os lebegőpontos szám
mem4r a memóriában tárol 4 byte-os lebegőpontos szám
mem10d a memóriában tárol 10 byte-os egész BCD szám
mem8i a memóriában tárol 8 byte-os egész (integer) szám
mem4i a memóriában tárol 8 byte-os egész (integer) szám
mem2i a memóriában tárol 8 byte-os egész (integer) szám
mem14 14 byte-os puffer a 8087 állapotának tárolására
mem94 94 byte-os puffer a 8087 állapotának tárolására

Az FST utasítás segítségével lehet a feltöltött számokat leszedni egy memóriacímre.
 

Utasítás Jelentés
FST ST(i) ST(i) <= ST(0)
FST mem4r Single <= ST(0) (Dword asm prefix.)
FST mem8r Double <= ST(0) (Qword)
FIST mem2i Integer <= ST(0) (Word)
FIST mem4i Longint <= ST(0) (Dword)
FSTP ST(i)  ST(i) <= ST(0), pop
FSTP mem10r Extended <= ST(0), pop (TByte)
FSTP mem4r Single <= ST(0), pop (DWord)
FSTP mem8r Double <= ST(0), pop (QWord)
FISTP mem2i Integer <= ST(0),pop (Word)
FISTP mem4i Longint <= ST(0),pop (DWord)
FISTP mem8i Comp <= ST(0),pop (QWord)
FBSTP mem10d mem10d <=ST(0), pop (TByte)

Milyen más általános utasítások vannak még?

  FXCH ST(i) ST(0) <=> ST(i) felcserélése   FXCH ST(0)       <=> ST(1) felcserélése   FLDPI      push, ST(0)-ba PI értékét rakja (3.1415...)   FLD1       push, ST(0)-ba 1-et rak   FLDZ       push, ST(0)-ba 0-t  rak
A négy alapművelet:

Összeadás
 

Utasítás Jelentés
FADD  ST(1) <= ST(1) + ST(0), pop
FADD ST(i)  ST(0) <= ST(0) + ST(i)
FADD ST(i), ST(0)  ST(i) <= ST(i) + ST(0)
FADDP ST(i), ST(0) ST(i) <= ST(i) + ST(0), pop
FADD mem4r  ST(0) <= ST(0) + Single
FADD mem8r  ST(0) <= ST(0) + Double
FIADD mem2i  ST(0) <= ST(0) + Integer
FIADD mem4i  ST(0) <= ST(0) + Longint

Kivonás
 

Utasítás Jelentés
FSUB  ST(1) <= ST(1) - ST(0), pop
FSUB ST(i)  ST(0) <= ST(0) - ST(i)
FSUB ST(i), ST(0)  ST(i) <= ST(i) - ST(0)
FSUBP ST(i), ST(0)  ST(i) <= ST(i) - ST(0), pop
FSUB mem4r  ST(0) <= ST(0) - Single
FSUB mem8r  ST(0) <= ST(0) - Double
FISUB mem2i  ST(0) <= ST(0) - Integer
FISUB mem4i  ST(0) <= ST(0) - Longint
FSUBR  ST(1) <= ST(0) - ST(1), pop
FSUBR ST(i)  ST(0) <= ST(i) - ST(0)
FSUBR ST(i), ST(0)  ST(i) <= ST(0) - ST(i)
FSUBRP ST(i), ST(0)  ST(i) <= ST(0) - ST(i), pop
FSUBR mem4r  ST(0) <= Single - ST(0)
FSUBR mem8r  ST(0) <= Double - ST(0)
FISUBR mem2i  ST(0) <= Integer - ST(0)
FISUBR mem4i  ST(0) <= Longint - ST(0)

Szorzás
 

Utasítás Jelentés
FMUL  ST(1) <= ST(1) * ST(0), pop
FMUL ST(i)  ST(0) <= ST(0) * ST(i)
FMUL ST(i), ST(0)  ST(i) <= ST(i) * ST(0)
FMULP ST(i), ST(0)  ST(i) <= ST(i) * ST(0), pop
FMUL mem4r  ST(0) <= ST(0) * Single
FMUL mem8r  ST(0) <= ST(0) * Double
FIMUL mem2i  ST(0) <= ST(0) * Integer
FIMUL mem4i  ST(0) <= ST(0) * Longint

Osztás
 

Utasítás Jelentés
FDIV  ST(1) <= ST(1) / ST(0), pop
FDIV ST(i)  ST(0) <= ST(0) / ST(i)
FDIV ST(i), ST(0)  ST(i) <= ST(i) / ST(0)
FDIVP ST(i), ST(0)  ST(i) <= ST(i) / ST(0), pop
FDIV mem4r  ST(0) <= ST(0) / Single
FDIV mem8r  ST(0) <= ST(0) / Double
FIDIV mem2i  ST(0) <= ST(0) / Integer
FIDIV mem4i  ST(0) <= ST(0) / Longint
FDIVR  ST(1) <= ST(0) / ST(1), pop
FDIVR ST(i)  ST(0) <= ST(i) / ST(0)
FDIVR ST(i), ST(0)  ST(i) <= ST(0) / ST(i)
FDIVRP ST(i), ST(0) ST(i) <= ST(0) / ST(i), pop
FDIVR mem4r  ST(0) <= Single / ST(0)
FDIVR mem8r  ST(0) <= Double / ST(0)
FIDIVR mem2i  ST(0) <= Integer / ST(0)
FIDIVR mem4i  ST(0) <= Longint / ST(0)

Összehasonlítás, vizsgálatok
 

Utasítás Jelentés
FCOM  CMP ST(0), ST(1)
FCOM ST(i)  CMP ST(0), ST(i)
FCOM mem4r  CMP ST(0), Single
FCOM mem8r  CMP ST(0), Double
FCOMP  CMP ST(0), ST(1), pop
FCOMP ST(i)  CMP ST(0), ST(i), pop
FCOMP mem4r  CMP ST(0), Single, pop
FCOMP mem8r  CMP ST(0), Double, pop
FCOMPP  CMP ST(0), ST(1), pop, pop (!)
FICOM mem2i  CMP ST(0), Integer
FICOM mem4i  CMP ST(0), Longint
FICOMP mem2i  CMP ST(0), Integer, pop
FICOMP mem4i  CMP ST(0), Longint, pop
  C3      C2      C1      C0
  0       0       ?       0       ST > op
  0       0       ?       1       ST < op
  1       0       ?       0       ST = op
  1       1       ?       1       ST nem hasonlítható össze

  FTST    CMP ST(0), 0.0

  C3      C2      C1      C0
  0       0       ?       0       ST > 0.0
  0       0       ?       1       ST < 0.0
  1       0       ?       0       ST = 0.0
  1       1       ?       1       ST nem hasonlítható össze

  FXAM    C3 -- C0 <= ST(0) típusa

Szögfüggvények
 

Utasítás Jelentés
FSIN  ST(0) <= Sin(ST(0)) {ST(0) radiánban !}
FCOS  ST(0) <= Cos(ST(0)) {ST(0) radiánban !}
FPTAN  push, ST(1) / ST(0) <= TAN( előző ST(0)) {0 < ST < pi/4}
FPATAN  ST(0) <= TAN( ST(1) / ST(0)), pop {FPTan inverze- arc Tan()}
FSQRT  ST(0) <= Sqrt( ST(0) ) {Az Sqrt() a négyzetgyököt jelenti}
FABS  ST(0) <= Abs ( ST(0) )
FCHS  ST(0) <= - ST(0)
FPREM  ST(0) <= REPEAT(ST(0) - ST(1)) {maradék}
FRNDINT  ST(0) <= Round(ST(0) - ST(1)) {kerekítés}

Koprocesszor inicializálás
 

Utasítás Jelentés
FINIT  Az FPU inicializálása, mindig használjuk ezt az FPU utasítások előszöri használata előtt
FENI  megszakítások engedélyezése
FDISI  megszakítások tiltása
FSTCW mem2i  Word <= 80x87 vezérlőszó
FLDWC  80x87 vezérlőszó <= mem2i
FSTSW  AX <= állapotszó

Beállító utasítások
 

Utasítás Jelentés
FSTSW mem2i  Word <= állapotszó
FSTENV mem14  Array[1..14] of Byte <= 80x87 környezete
FLDENV mem14  80x87 környezete <= Array[1..14] of Byte
FSAVE mem94  Array[1..94] of Byte <= a 80x87 állapota
FRSTOR mem94  a 80x87 állapota <= Array[1..94] of Byte

Egyéb utasítások
 

Utasítás Jelentés
FINCSTP  a stack pointer növelése (az elemek eggyel feljebb kerülnek)
FDECSTP  a stack pointer csökkentése (az elemek eggyel leljebb kerülnek)
FFREE ST(i) az ST(i) stack-elem ill. regiszter kiüresítése
FNOP  üres művelet
FWAIT  wait utasítás (várakozás)
FSETPM  a protected mód beállítása (80287+)
  ---------------------------[ SINUS DRAWER ]-----------------------------   org      100h   section  .text   start:            push         cs            pop          ds            finit            fldpi                               ; PI-t berakjuk a verembe            fidiv        word [_180]            ; elosztjuk 180-nal, mivel            fstp         dword [osztott]        ; 1 fok= PI/180 radián            push         word 0a000h            ; Videómemória kezdQ.címe            pop          es                     ;            mov          ax,13h                 ; 320x200x256-os mód            int          10h            xor          bp,bp            mov          cx,320                 ; 320-szor megyünk     @go:   mov          [szoroz],bp            ; szoroz=0..319, a            fld          dword [osztott]        ; szögszámláló benyomjuk            fimul        word [szoroz]          ; beszorozzuk, az aktuális            fsin                                ; szög szinuszát adja vissza            fimul        word [bigszam]         ; hogy lássuk is            fistp        word [y]               ; y=sin(A)            mov          ax,[y]            add          ax,100                 ; középreigazítás            mov          bx,320            mul          bx            add          ax,[x]            mov          di,ax                  ; di=320*(y+100)+x            mov          al,15            stosb                               ; es:[di]:=al            inc          word [x]            inc          bp            loop         @go            xor          ax,ax                  ; várunk egy gombra            int          16h            mov          ax,3            int          10h            ret   section  .data            szoroz       dw 1                   ; Ez a szögszámláló            y            dw 0            x            dw 0            _180         dw 180                 ; A PI/180-hoz kell            bigszam      dw 60                  ; Ezzel szorozzuk fel ..            osztott      dd 0                   ; = PI/180   section .bss   ---------------------------[ END ]-----------------------------