Architektura Komputerów/Wykład 4: Struktura modelu programowego

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania

ASK M4 S01.png

ASK M4 S02.png

ASK M4 S03.png

Użytkowy model programowy – to zbiór zasobów logicznych komputera widzianych przez programistę lub kompilator. Model programowy nie ma jednoznacznego i bezpośredniego związku z implementacją, czyli budową procesora i komputera. Istnieje wiele rodzin komputerów czy procesorów o wspólnym modelu programowym i wielu odmiennych implementacjach. Przykładem może to być rodzina x86 (zapoczątkowana w 1976 roku) lub IBM zSeries, wywodząca się z lat 60-tych XX wieku.


ASK M4 S04.png

ASK M4 S05.png

ASK M4 S06.png

Rejestry procesora mogą pełnić różne role w programach.

Akumulatorem nazywamy rejestr, który może być użyty jako argument źródła i równocześnie przeznaczenia dla operacji arytmetycznej lub logicznej.

Rejestr służący do uzyskania adresu danej umieszczonej w pamięci nazywa się ogólnie rejestrem adresowym. Jeśli rejestr może być użyty w trybie adresowania rejestrowym pośrednim, jest on nazywany rejestrem bazowym.

Rejestr może również służyć do odliczania iteracji pętli. Rejestr przewidziany do takiego zastosowania nazywa się licznikiem pętli.


ASK M4 S07.png

istnieje wiele różnych koncepcji organizacji zestawu rejestrów – począwszy od architektur bezrejestrowych a skończywszy na architekturach z bardzo dużym zestawem rejestrów o liczebności przekraczającej 100.


ASK M4 S08.png

Architektury bezrejestrowe, określane również mianem „pamięć-pamięć”, nie przechowują danych w rejestrach procesora. Procesor jest wyposażony w kilka rejestrów, które służą wyłącznie do przechowywania adresów.

Szczególną postacią architektury bezrejestrowej jest architektura MOVE. W architekturach tego typu procesor wykonuje tylko jedną lub co najwyżej kilka instrukcji, których argumentami mogą być wyłącznie stałe lub adresy pamięci. operacje arytmetyczne i logiczne są realizowane poprzez przesłania do specjalnych lokacji pamięci, służących jako rejestry argumentów. Adresy tych lokacji są używane do wyboru operacji wykonywanej przez jednostkę arytmetyczną.


ASK M4 S09.png

Architektury z minimalnym zestawem rejestrów posiadają jeden lub dwa akumulatory i jeden lub dwa rejestry adresowe. niemal wszystkie instrukcje wymagają odwołania do pamięci, ale jeden z argumentów instrukcji zwykle znajduje się w rejestrze. Generowanie kodu dla takich procesorów jest proste, ale uzyskany program wykonuje się stosunkowo wolno wskutek dużej liczby odwołań do pamięci.

Architektury tego typu nie są stosowane w komputerach uniwersalnych, były one natomiast popularne w mikrokontrolerach.


ASK M4 S10.png

Rysunek przedstawia zestaw rejestrów jednostki wykonawczej mikrokontrolera rodziny HC08. Argumenty i zmienne lokalne procedur są tu adresowana względem wskaźnika stosu, a wielofunkcyjny rejestr HX służy jako rozszerzenie akumulatora dla operacji mnożenia i dzielenia, rejestr adresowy i licznik pętli. Podstawowym akumulatorem jest rejestr A.

Mały zestaw rejestrów wymusza umieszczanie niektórych zmiennych roboczych (tymczasowych) w pamięci.


ASK M4 S11.png

W architekturach z małym zestawem rejestrów specjalizowanych mamy do czynienia z zestawem kilku rejestrów, niekiedy częściowo uniwersalnych, które są argumentami domyślnymi wielu specyficznych instrukcji.

Ponieważ kompilator używa czasem instrukcji, których argumenty muszą być umieszczone w konkretnych rejestrach, rejestry nie mogą być użyte do przechowywania danych programu (argumentów i zmiennych lokalnych procedur). Służą one jedynie do przechowywania tymczasowych wyników obliczeń oraz jako argumenty instrukcji, z którymi są domyślnie związane.

Pomimo, że pojemność zestawu rejestrów jest znacząca, kompilator nie jest w stanie efektywnie korzystać z rejestrów.


ASK M4 S12.png

Rysunek przedstawia zestaw podstawowych rejestrów jednostki stałopozycyjnej 16-bitowej wersji architektury x86, zapoczątkowanej modelem Intel 8086 w 1976 roku. Poszczególne 16-bitowe rejestry są „przywiązane” do niektórych instrukcji. Tylko cztery rejestry mogą być używane jako adresowe.

Stosunkowo najbardziej uniwersalnymi rejestrami są SI i DI, ale ich użycie jest ograniczone przez fakt, że nie jest dostępny ich najmniej znaczący bajt. Niektóre bardziej zaawansowane kompilatory dla x86 używały tych dwóch rejestrów do alokacji zmiennych lokalnych procedury.


ASK M4 S13.png

W architekturach z małym zestawem rejestrów uniwersalnych mamy do czynienia z zestawem około 8 rejestrów, z których przynajmniej 5 daje się użyć w dowolnym charakterze – jako akumulatory lub rejestry adresowe.

Przykładem jest tu 32-bitowa wersja x86, zapoczątkowana przez model 80386 w roku 1985. Rejestry odziedziczone po wersji 16-bitowej zostały rozszerzone do 32 bitów. Wprowadzono również nowy zestaw trybów adresowania, umożliwiający wykorzystanie do adresowania wszystkich rejestrów. Wprowadzenie nowych instrukcji mnożenia umożliwiło zmniejszenie „przywiązania rejestrów do instrukcji. W ten sposób, pomimo, że na pierwszy rzut oka model programowy wygląda bardzo podobnie do wcześniejszych wersji, kompilator może używać rejestrów znacznie elastyczniej niż we wcześniejszych procesorach tej rodziny.


ASK M4 S14.png

W architekturach z dużym zestawem rejestrów mamy do czynienia z wieloma rejestrami, które mogł pełnić dowolną rolę. Umożliwia to kompilatorom używanie rejestrów do przekazywania argumentów wywołania i zmiennych lokalnych procedury.

Odwołania do pamięci zostają skupione w prologu i epilogu procedury, gdzie zachodzi przeładowanie ramki stosu pomiędzy rejestrami i stosem w pamięci.


ASK M4 S15.png

W niektórych architekturach bardzo duży zestaw rejestrów jest używany do zbuforowania wewnątrz procesora wierzchołka stosu umieszczonego w pamięci. W ten sposób uzyskuje się znaczną redukcję liczby odwołań do pamięci, również w prologu i epilogu procedury.

Ponieważ zestaw rejestrów mieści kilka ramek stosu, odwołania do pamięci zachodzą przy przepełnieniu lub niedopełnieniu stosu w rejestrach, co ma miejsce raz na kilka poziomów wywołań procedur.


ASK M4 S16.png

W architekturach ze stosowym zestawem rejestrów rejestry są zorganizowane w postaci niewielkiego stosu. Ponieważ operacje są domyślnie wykonywane na wierzchołku stosu, procesory o takich zestawach rejestrów mają zwykle instrukcje bezargumentowe lub jednoargumentowe.

Taka architektura zestawu rejestrów znacząco upraszcza konstrukcję kompilatora, jest ona jednak bardzo trudna do efektywnej realizacji przy typowych współczesnych strukturach jednostek wykonawczych.


ASK M4 S17.png

Drugim elementem modelu programowego jest zestaw trybów adresowania. Samo pojęcie trybu adresowania ma dwa znaczenia.


ASK M4 S18.png

ASK M4 S19.png

ASK M4 S20.png

Można zauważyć, że w celu umożliwienia efektywnej implementacji języków wysokiego poziomu procesor powinien posiadać trzy tryby adresowania.

Tryb natychmiastowy służy do ładowania do rejestrów stałych, w tym również adresów danych statycznych. Tryb rejestrowy bezpośredni umożliwia użycie zawartości rejestru jako argumentu operacji. Do adresowania danych w pamięci wystarczy jeden z trybów rejestrowych pośrednich. W ten sposób uzyskujemy możliwość adresowania zmiennym adresem, wyliczonym uprzednio w rejestrze. Adresowanie danych stałym adresem może być potraktowane jako szczególny przypadek adresowania ze zmiennym adresem. Najwygodniejszym trybem adresowania pamięci jest tryb rejestrowy pośredni z przemieszczeniem.


ASK M4 S21.png

ASK M4 S22.png

Tryby rejestrowe pośrednie z bazą w liczniku instrukcji umożliwiają adresowanie danych względem adresu bieżącej instrukcji. Mogą one być używane do adresowania danych wplecionych w kod i logicznie należących do kodu programu (np. tablice adresów). W procesorach 64-bitowych tryby te umożliwiają ograniczenie długości adresów absolutnych zawartych w zapisie instrukcji, gdyż dane, przynajmniej statyczne, są zwykle położone niezbyt daleko od kodu programu. (W przeciwnym razie zamiast 32-bitowych przemieszczeń względem PC do adresowania danych należałoby używać 64-bitowych adresów absolutnych.)

Problem obliczania zmieniających się z każdą instrukcją przemieszczeń danych liczonych względem PC przejmuje na siebie asembler.


ASK M4 S23.png

ASK M4 S24.png

ASK M4 S25.png

W trybach pamięciowych pośrednich jeden z elementów adresu jest pobierany z pamięci, a uzyskany adres jest wykorzystywany do odwołania do danej w pamięci. Odwołanie do danej wymaga więc dwukrotnego sięgnięcia do pamięci.

W trybach pamięciowych pośrednich występują dwa adresy efektywne, do obliczenia których można korzystać z operacji indeksowania lub dodawania przemieszczenia. Pierwszy adres, wyznaczony z jednego z omówionych wcześniej trybów adresowania pamięci, jest używany do odczytania wartości, służącej jako adres bazowy dla drugiego adresu. Do pozyskanego w ten sposób adresu bazowego można następnie dodać przemieszczenie lub przeskalowaną zawartość rejestru indeksowego.

Tryby pamięciowe pośrednie były charakterystyczne dla złożonych architektur CISC. Obecnie są one rzadko spotykane, gdyż opisana sekwencja operacji może być łatwo, a zarazem w sposób bardziej elastyczny, zrealizowana na drodze programowej.


ASK M4 S26.png

Model operacji warunkowych jest trzecim składnikiem modelu programowego. Współczesne procesory implementują jeden z trzech modeli opisanych w dalszym ciągu wykładu.


ASK M4 S27.png

Model ze znacznikami wprowadza dwufazową realizację operacji warunkowych, przy czym instrukcje procesora realizujące obie fazy mogą być rozsunięte w czasie.

W pierwszej fazie w wyniku wykonania operacji arytmetycznej lub logicznej zostają ustawione znaczniki – jednobitowe rejestry atrybutów wyniku. W drugiej fazie następuje wykonanie operacji zależne od stanu znaczników.


ASK M4 S28.png

W poszczególnych architekturach występuje od dwóch do sześciu znaczników. typowa liczba znaczników wynosi 4.Dwa ostatnie – przeniesienie pomocnicze i parzystość, występują głównie w architekturach wywodzących się z lat 70-tych XX wieku.

Znacznik przeniesienia pomocniczego wspomaga realizację operacji na liczbach zapisanych w kodzie BCD. Przechowuje on wartość przeniesienia pomiędzy tetradami pojedynczego bajtu reprezentującymi cyfry dziesiętne.

Znacznik parzystości był używany do podstawowej kontroli poprawności transmisji danych znakowych w kodzie ASCII, w tym do kontroli danych odczytywanych z taśm perforowanych. Nawet w procesorach 32- i 64-bitowych znacznik parzystości zawsze dotyczy wyłącznie najmniej znaczącego bajtu wyniku operacji.


ASK M4 S29.png

Ponieważ w różnych architekturach obowiązują różne konwencje ustawiania znaczników, rozpoczynając programowanie procesora w asemblerze należy dokładnie zapoznać się z dokumentacją poszczególnych instrukcji.


ASK M4 S30.png

Instrukcja warunkowa realizuje drugą fazę operacji warunkowej w modelu ze znacznikami. Jest to instrukcja, której sposób wykonania zależy od wartości znaczników. Instrukcja warunkowa specyfikuje warunek wykonania. Jeśli warunek (wyrażenie logiczne na znacznikach) jest spełniony, instrukcja wykonuje zadaną operację (np. skok lub przesłanie). W przeciwnym razie instrukcja wykonuje się jako pusta.

Instrukcja ustawienia danej (np. SETcc w x86) wpisuje do rejestru wartość logiczną warunku wyrażoną jako stałą całkowitą.

W niektórych architekturach większość instrukcji jest wykonywanych jako warunkowe.


ASK M4 S31.png

Warunek wykonania jest jednym z predefiniowanych w danej architekturze wyrażeń logicznych na znacznikach. Poszczególne warunki mają swoje nazwy mnemoniczne.


ASK M4 S32.png

Rysunek przedstawia rozmieszczenie znaczników w rejestrze stanu procesorów rodziny x86.


ASK M4 S33.png

Tabela zawiera nazwy symboliczne warunków dostępnych w x86 i specyfikację odpowiadających im wyrażeń logicznych na znacznikach.

Należy zwrócić uwagę na istnienie wielu nazw tych samych warunków, co ułatwia ich użycie w programach.

Stosowane w nazwach warunków skróty A, B, G i L (above, below, greater, less) oznaczają odpowiednio relacje większości i mniejszości dla liczb bez znaku (A, B) i ze znakiem (G, L).


ASK M4 S34.png

W modelu operacji warunkowych bez znaczników operacja warunkowa jest realizowana przez pojedynczą instrukcję. instrukcja ta ewaluuje wartość logiczną relacji, a następnie wykonuje jakąś czynność, jeśli relacja jest spełniona.

Taki model operacji warunkowych jest prosty i wydajny w implementacji. jest on stosowany w prostych architekturach RISCowych.


ASK M4 S35.png

Model z predykatami jest spotykany w nowych architekturach o dużej równoległości wykonania instrukcji, dużych zestawach rejestrów i wysokich kosztach skoków. praktycznie jedyną architekturą komercyjną implementującą ten model jest IA-64.