Ponieważ system 32-bitowy nie może zarządzać liczbą 2 ^ 33 (ponieważ oczywisty limit 32-bitowy), w jaki sposób można zarządzać 80-bitową liczbą zmiennoprzecinkową ?
Powinien wymagać „80-bit”…
Ponieważ system 32-bitowy nie może zarządzać liczbą 2 ^ 33 (ponieważ oczywisty limit 32-bitowy), w jaki sposób można zarządzać 80-bitową liczbą zmiennoprzecinkową ?
Powinien wymagać „80-bit”…
Odpowiedzi:
Jednym ze znaczeń 32-bitowego procesora jest to, że jego rejestry mają szerokość 32 bitów. Nie oznacza to, że nie może poradzić sobie z liczbami 64-bitowymi, tylko że najpierw musi poradzić sobie z dolną 32-bitową połową, a następnie z górną 32-bitową połową sekundy. (Właśnie dlatego procesory mają flagę przenoszenia .) Jest wolniejszy niż, jeśli procesor mógłby po prostu załadować wartości do szerszego 64-bitowego rejestru, ale nadal jest to możliwe.
Zatem „bitowość” systemu niekoniecznie ogranicza rozmiar liczb, z którymi program może sobie poradzić, ponieważ zawsze można rozbić operacje, które nie mieszczą się w rejestrach procesora, na wiele operacji. Spowalnia więc operacje, zużywa więcej pamięci (jeśli musisz użyć pamięci jako „notatnika”) i trudniej ją programować, ale operacje są nadal możliwe.
Jednak nic z tego nie ma znaczenia, na przykład, dla 32-bitowych procesorów Intel i liczb zmiennoprzecinkowych, ponieważ zmiennoprzecinkowa część procesora ma własne rejestry i mają one szerokość 80 bitów. (Na początku historii x86 funkcja zmiennoprzecinkowa była osobnym układem, była zintegrowana z procesorem od 80486DX.)
Odpowiedź @ Breakthrough zainspirowała mnie do dodania tego.
Wartości zmiennoprzecinkowe, o ile są przechowywane w rejestrach FPU, działają zupełnie inaczej niż binarne wartości całkowite.
80 bitów wartości zmiennoprzecinkowej jest dzielonych między mantysę i wykładnik potęgi (istnieje również „podstawa” w liczbach zmiennoprzecinkowych, która zawsze wynosi 2). Mantysa zawiera cyfry znaczące, a wykładnik określa, jak duże są te cyfry znaczące. Więc nie ma „przelewu” do innego rejestru, jeśli twoja liczba staje się zbyt duża, aby zmieścić się w mantysie, twój wykładnik rośnie i tracisz precyzję - tzn. Kiedy zamienisz ją na liczbę całkowitą, stracisz miejsca po przecinku z prawej strony - dlatego nazywa się to zmiennoprzecinkowe.
Jeśli wykładnik jest zbyt duży, wówczas występuje przepełnienie zmiennoprzecinkowe, ale nie można go łatwo rozszerzyć na inny rejestr, ponieważ wykładnik i mantysa są ze sobą powiązane.
Mógłbym być trochę nieprecyzyjny i mylić się co do niektórych z tego, ale wierzę, że to sedno tego. (Ten artykuł w Wikipedii ilustruje to nieco bardziej zwięźle.)
Jest OK, że działa to zupełnie inaczej, ponieważ cała „zmiennoprzecinkowa” część procesora jest jakby w swoim własnym świecie - do uzyskania dostępu do niego używasz specjalnych instrukcji procesora. Ponadto, jeśli chodzi o kwestię pytania, ponieważ jest osobna, bitowość FPU nie jest ściśle powiązana z bitami natywnego procesora.
źródło
-fomit-frame-pointer
aby odzyskać ten rejestr.Wszystkie wersje 32-bitowe, 64-bitowe i 128-bitowe odnoszą się do długości słowa procesora, którą można uznać za „podstawowy typ danych”. Często jest to liczba bitów przesłanych do / z pamięci RAM systemu i szerokość wskaźników (chociaż nic nie powstrzymuje Cię przed użyciem oprogramowania w celu uzyskania dostępu do większej ilości pamięci RAM niż dostęp do pojedynczego wskaźnika).
Zakładając stałą szybkość zegara (a także wszystko inne w architekturze są stałe) i zakładając, że odczyt / zapis pamięci jest taki sam (zakładamy tutaj 1 cykl zegara, ale w rzeczywistości jest to dalekie od rzeczywistego), możesz dodaj dwie 64-bitowe liczby w jednym cyklu zegara na komputerze 64-bitowym (trzy, jeśli policzysz pobieranie liczb z pamięci RAM):
Możemy również wykonać to samo obliczenie na maszynie 32-bitowej ... Jednak na maszynie 32-bitowej musimy to zrobić w oprogramowaniu, ponieważ najpierw należy dodać niższe 32-bity, skompensować przepełnienie, a następnie dodać górne 64 bity:
Przeglądając moją złożoną składnię, możesz łatwo zobaczyć, w jaki sposób operacje o wyższej precyzji mogą zajmować wykładniczo dłuższy czas na maszynie o mniejszej długości słów. To jest prawdziwy klucz do procesorów 64-bitowych i 128-bitowych: pozwalają nam obsługiwać większą liczbę bitów w jednej operacji. Niektóre maszyny zawierają instrukcje dodawania innych ilości z przeniesieniem (np.
ADC
Na x86), ale powyższy przykład ma na myśli dowolne wartości precyzji.Teraz, aby rozszerzyć to na pytanie, łatwo jest zobaczyć, jak moglibyśmy dodać liczby większe niż dostępne rejestry - po prostu dzielimy problem na części wielkości rejestrów i pracujemy od tego miejsca. Chociaż, jak wspomniano w @MatteoItalia , stos FPU x87 ma natywną obsługę dla wielkości 80-bitowych, w systemach pozbawionych tego wsparcia (lub procesorów całkowicie pozbawionych jednostki zmiennoprzecinkowej!), Równoważne obliczenia / operacje muszą być wykonane w oprogramowaniu .
Tak więc dla liczby 80-bitowej po dodaniu każdego segmentu 32-bitowego można również sprawdzić przepełnienie do 81-go bitu i opcjonalnie wyzerować bity wyższego rzędu. Te kontrole / zera są wykonywane automatycznie dla niektórych instrukcji x86 i x86-64, w których podane są rozmiary operandu źródłowego i docelowego (chociaż są one określone tylko w potęgach 2, zaczynając od szerokości 1 bajta).
Oczywiście przy liczbach zmiennoprzecinkowych nie można po prostu wykonać dodawania binarnego, ponieważ mantysa i cyfry znaczące są spakowane razem w formie przesunięcia. W jednostce ALU procesora x86 znajduje się obwód sprzętowy do wykonania tego dla pływaków 32-bitowych i 64-bitowych IEEE; jednak nawet przy braku jednostki zmiennoprzecinkowej (FPU), te same obliczenia mogą być wykonywane w oprogramowaniu (np. za pomocą Biblioteki Naukowej GNU , która używa FPU po kompilacji na architekturze, wracając do algorytmów oprogramowania jeśli nie jest dostępny sprzęt zmiennoprzecinkowy [np. dla wbudowanych mikrokontrolerów bez FPU]).
Biorąc pod uwagę wystarczającą ilość pamięci, można również wykonać obliczenia na podstawie liczby dowolnych (lub „nieskończonych” - w granicach realistycznych) precyzji, wykorzystując więcej pamięci, ponieważ wymagana jest większa precyzja. Jedna z tych implementacji istnieje w bibliotece GNU Multiple Precision , co pozwala na nieograniczoną precyzję (oczywiście do momentu zapełnienia pamięci RAM) operacji na liczbach całkowitych, wymiernych i zmiennoprzecinkowych.
źródło
Architektura pamięci systemu może umożliwiać przenoszenie tylko 32 bitów jednocześnie - ale to nie powstrzymuje go przed użyciem większych liczb.
Pomyśl o pomnożeniu. Możesz znać swoje tabliczki mnożenia do 10x10, ale prawdopodobnie nie masz problemu z wykonaniem 123x321 na kartce papieru: po prostu rozbijasz go na wiele małych problemów, mnożąc poszczególne cyfry i dbając o przenoszenie itp.
Procesory mogą zrobić to samo. W „dawnych czasach” miałeś 8-bitowe procesory, które mogły wykonywać obliczenia zmiennoprzecinkowe. Ale były powolne.
źródło
„32-bit” to tak naprawdę sposób kategoryzowania procesorów, a nie ustalenie reguły. „32-bitowy” procesor zazwyczaj ma 32-bitowe rejestry ogólnego przeznaczenia do pracy.
Jednak nie ma żadnych wymagań, aby wszystko w procesorze odbywało się w wersji 32-bitowej. Na przykład nie było niespotykane, aby komputer „32-bitowy” miał 28-bitową magistralę adresową, ponieważ wytwarzanie sprzętu było tańsze. Komputery 64-bitowe często mają 40-bitową lub 48-bitową szynę pamięci z tego samego powodu.
Arytmetyka zmiennoprzecinkowa to kolejne miejsce, w którym rozmiary się różnią. Wiele 32-bitowych procesorów obsługuje 64-bitowe liczby zmiennoprzecinkowe. Dokonali tego, przechowując wartości zmiennoprzecinkowe w specjalnych rejestrach, które były szersze niż rejestry ogólnego przeznaczenia. Aby zapisać jedną z tych dużych liczb zmiennoprzecinkowych w rejestrach specjalnych, należy najpierw podzielić liczbę na dwa rejestry ogólnego przeznaczenia, a następnie wydać instrukcję łączenia ich w liczbę zmiennoprzecinkową w rejestrach specjalnych. W rejestrach zmiennoprzecinkowych wartości byłyby zmieniane jako zmiennoprzecinkowe 64-bitowe, a nie jako para 32-bitowych połówek.
Wspomniana 80-bitowa arytmetyka jest tego szczególnym przypadkiem. Jeśli pracujesz z liczbami zmiennoprzecinkowymi, znasz niedokładność wynikającą z problemów z zaokrąglaniem liczb zmiennoprzecinkowych. Jednym z rozwiązań dla zaokrąglania jest posiadanie większej ilości precyzji, ale następnie musisz przechowywać większe liczby i zmuszać programistów do używania w pamięci niezwykle dużych wartości zmiennoprzecinkowych.
Rozwiązanie firmy Intel polega na tym, że wszystkie rejestry zmiennoprzecinkowe mają 80 bitów, ale instrukcje przenoszenia wartości do / z tych rejestrów działają przede wszystkim na liczbach 64-bitowych. Dopóki działasz całkowicie w ramach zmiennoprzecinkowego stosu Intela x87, wszystkie twoje operacje są wykonywane z 80 bitami precyzji. Jeśli twój kod musi wyciągnąć jedną z tych wartości z rejestrów zmiennoprzecinkowych i zapisać ją gdzieś, obcina ją do 64-bitów.
Morał tej historii: kategorie, takie jak „32-bit”, są zawsze bardziej ryzykowne, gdy zagłębisz się w rzeczy!
źródło
„32-bitowy” procesor to taki, w którym większość rejestrów danych to rejestry 32-bitowe, a większość instrukcji działa na danych w tych rejestrach 32-bitowych. 32-bitowy procesor może również przesyłać dane do iz pamięci 32-bitowej jednocześnie. Większość rejestrów w wersji 32-bitowej nie oznacza, że wszystkie rejestry są 32-bitowe. Krótka odpowiedź jest taka, że 32-bitowy procesor może mieć pewne funkcje, które wykorzystują inne liczby bitów, takie jak 80-bitowe rejestry zmiennoprzecinkowe i odpowiednie instrukcje.
Jak powiedział @spudone w komentarzu do odpowiedzi @ ultrasawblade, pierwszym procesorem x86, który miał zintegrowane operacje zmiennoprzecinkowe, był Intel i486 (konkretnie 80486DX, ale nie 80486SX), który zgodnie ze stroną 15-1 programistów mikroprocesorów i486 Podręcznik odniesienia zawiera w swoich rejestrach numerycznych „Osiem 80-bitowych rejestrów numerycznych indywidualnie adresowanych”. I486 ma 32-bitową magistralę pamięci, więc przesłanie wartości 80-bitowej zajęłoby 3 operacje pamięci.
Poprzednik generacji 486, i386, nie miał żadnych zintegrowanych operacji zmiennoprzecinkowych. Zamiast tego miał obsługę zewnętrznego „zmiennoprzecinkowego” zmiennoprzecinkowego, 80387. Ten koprocesor miał prawie taką samą funkcjonalność jak zintegrowany z i486, jak można zobaczyć na stronie 2-1 80387 Podręcznik programisty .
80-bitowy format zmiennoprzecinkowy wydaje się pochodzić z 8087, koprocesora matematycznego dla 8086 i 8088. 8086 i 8088 były 16-bitowymi procesorami (z 16-bitowymi i 8-bitowymi szynami pamięci) i nadal były w stanie użyć 80-bitowego formatu zmiennoprzecinkowego, korzystając z 80-bitowych rejestrów w koprocesorze.
źródło