Koprocesor - podstawy
Twój komputer prawie napewno wyposażony jest w bardzo fajną zabawkę, jaką jest koprocesor. Coś takiego stosowano już nawet do pierwszych PC'tów, jednak dopiero od pentium zaczął on być szybki, a nawet szybszy w obliczeniach od samego procesora! Okazuje się, że komputer szybciej policzy na koprocesorze ile jest 5.1243123 razy 3.123123 niż na procesorze ile jest 5 razy 3 ! To pierwsze zajmie 3 takty (a przy dobrym kodowaniu - jeden), to drugie natomiast aż 9. Z dzieleniem nie ma już wielkiej różnicy (o ile pamiętam 39 taktów zamiast 42), ale... o tym za chwilę.
Koprocesor potrafi komunikować się z pamięcią, z własnym stosem (czyli właściwie też pamięcią), natomiast nie potrafi czytać rejestrów procesora. Oznacza to, że aby wysłać zawartość rejestru EAX na stos koprocesora, musimy najpierw wysłać go do jakiejś zmiennej, a potem dopiero wczytać koprocesorem.
Wszystkie dane na stosie koprocesora przechowywane są jako liczby rzeczywiste. Jeżeli wczytamy zmienną całkowitą - jest ona konwertowana na rzeczywistą, co zabiera odpowiednio dużo czasu. Analogicznie jest przy wysyłaniu do pamięci zmiennych całkowitych. Dlatego przy korzystaniu z koprocesora należy unikać liczb całkowitych, najlepiej korzystać z nich dopiero pod koniec - gdy są naprawdę potrzebne. W moim engine-3D na floatach było praktycznie wszystko i integery pojawiły się dopiero przy współrzędnych ekranowych.
Podstawowe instrukcje:
FLD - wczytaj z pamięci na stos
FST - zapisz ze stosu do pamięci, nie usuwając ze stosu
FSTP - jak FST, ale z usunięciem danej ze stosu
FADD - dodawanie - dodaj dwie dane z wierzchołka stosu, usuń je i zapisz wynik na wierzchołku
FSUB - odejmowanie
FMUL - mnożenie
FDIV - dzielenie
FILD - wczytaj daną całkowitą, przekonwertuj ją i zapisz na stosie
FIST - przekonwertuj daną ze stosu na całkowitą i wyślij do pamięci
FISTP - jak FIST ale z usunięciem ze stosu
FSQRT - pierwiastek kwadratowy z liczby na wierzchołku stosu
FSIN - sinus
FCOS - cosinus
FPATAN - arctangens (przyjmuje dwa argumenty, ten drugi najlepiej ustawić jako 1.0)
Neleżałoby jeszcze dodać, jak tworzyć w Turbo Assemblerze zmienne typu rzeczywistego. Musimy na taką zmienną poświęcić co najmniej 4 bajty, czyli musi być zadeklarowana jako DD . Jeżeli chcemy przypisać jej na początku jakąś wartość, trzeba użyć w niej kropki (przecinka numerycznego), nawet, jeżeli część ułamkowa równa jest zero:
Jedną z najciekawszych cech koprocesora jest to, że może on pracować wtedy, gdy pracuje tez procesor. Można to wykorzystać np. do wykonania dwóch dzieleń na raz:
...dzielenia wykonają się praktycznie w tym samym czasie, czyli dwa razy szybciej, niż gdyby wykonywały się oddzielnie.
Nie jest jednak tak fajnie, aby pracę można było zawsze podzielić pomiędzy procesor a koprocesor. W trakcie fdiv procesor nie może mnożyć. Nie przeszadza to jednak mu wykonywać wielu innych instrukcji. Jest to wykorzystywane przy korekcji perspektywy, gdy koprocesor oblicza iloraz, podczas gdy procesor rysuje na ekranie teksturkę.
Koprocesor potrafi komunikować się z pamięcią, z własnym stosem (czyli właściwie też pamięcią), natomiast nie potrafi czytać rejestrów procesora. Oznacza to, że aby wysłać zawartość rejestru EAX na stos koprocesora, musimy najpierw wysłać go do jakiejś zmiennej, a potem dopiero wczytać koprocesorem.
Wszystkie dane na stosie koprocesora przechowywane są jako liczby rzeczywiste. Jeżeli wczytamy zmienną całkowitą - jest ona konwertowana na rzeczywistą, co zabiera odpowiednio dużo czasu. Analogicznie jest przy wysyłaniu do pamięci zmiennych całkowitych. Dlatego przy korzystaniu z koprocesora należy unikać liczb całkowitych, najlepiej korzystać z nich dopiero pod koniec - gdy są naprawdę potrzebne. W moim engine-3D na floatach było praktycznie wszystko i integery pojawiły się dopiero przy współrzędnych ekranowych.
Podstawowe instrukcje:
FLD - wczytaj z pamięci na stos
FST - zapisz ze stosu do pamięci, nie usuwając ze stosu
FSTP - jak FST, ale z usunięciem danej ze stosu
FADD - dodawanie - dodaj dwie dane z wierzchołka stosu, usuń je i zapisz wynik na wierzchołku
FSUB - odejmowanie
FMUL - mnożenie
FDIV - dzielenie
FILD - wczytaj daną całkowitą, przekonwertuj ją i zapisz na stosie
FIST - przekonwertuj daną ze stosu na całkowitą i wyślij do pamięci
FISTP - jak FIST ale z usunięciem ze stosu
FSQRT - pierwiastek kwadratowy z liczby na wierzchołku stosu
FSIN - sinus
FCOS - cosinus
FPATAN - arctangens (przyjmuje dwa argumenty, ten drugi najlepiej ustawić jako 1.0)
Neleżałoby jeszcze dodać, jak tworzyć w Turbo Assemblerze zmienne typu rzeczywistego. Musimy na taką zmienną poświęcić co najmniej 4 bajty, czyli musi być zadeklarowana jako DD . Jeżeli chcemy przypisać jej na początku jakąś wartość, trzeba użyć w niej kropki (przecinka numerycznego), nawet, jeżeli część ułamkowa równa jest zero:
promyczek dd 1000.0
skala dd 1.5
prędkość dd ?
skala dd 1.5
prędkość dd ?
Jedną z najciekawszych cech koprocesora jest to, że może on pracować wtedy, gdy pracuje tez procesor. Można to wykorzystać np. do wykonania dwóch dzieleń na raz:
fild [_zmienna1]
fild [_zmienna2]
mov eax,[_zmienna3]
mov ebx,[_zmienna4]
fdiv
idiv ebx
fild [_zmienna2]
mov eax,[_zmienna3]
mov ebx,[_zmienna4]
fdiv
idiv ebx
...dzielenia wykonają się praktycznie w tym samym czasie, czyli dwa razy szybciej, niż gdyby wykonywały się oddzielnie.
Nie jest jednak tak fajnie, aby pracę można było zawsze podzielić pomiędzy procesor a koprocesor. W trakcie fdiv procesor nie może mnożyć. Nie przeszadza to jednak mu wykonywać wielu innych instrukcji. Jest to wykorzystywane przy korekcji perspektywy, gdy koprocesor oblicza iloraz, podczas gdy procesor rysuje na ekranie teksturkę.
Autorem tekstu jest:
Jacek Popławski
Materiał dodany przez użytkownika: alphan
