Aby dobrze rozumieć zasadę programowania w językach tak niskiego poziomu konieczna jest dobra znajomość programowanego sprzętu. Z punktu widzenia programisty będą Cię interesowały takie elementy, jak:

  • procesor
  • pamięć
  • urządzenia wejścia-wyjścia

Procesor

edytuj

Nie zostanie tu oczywiście opisane, jak np. przylutować procesor do płyty głównej, a jedynie kilka niezbędnych wiadomości z zakresu działania komputera. Najogólniej mówiąc procesor dzieli się na jednostkę wykonawczą EU (ang. Execution Unit) oraz jednostkę sterującą (ang. Control Unit). Poniżej zamieszczony został schemat budowy procesora. Oto i on:  

Jednostka sterująca:

  • IR - rejestr rozkazów (ang. Instruction Register). Przechowywany jest tutaj kod aktualnie wykonywanego polecenia, czyli rozkazu procesora pobranego z pamięci.
  • IU - dekoder rozkazów (ang. Instruction Unit). Tutaj dany rozkaz jest dekodowany, czyli określany zostaje rodzaj rozkazu. Innymi słowy tutaj procesor dekoduje rozkaz i "myśli" jak ten rozkaz wygląda i co z nim dalej zrobić. Na tej podstawie układ sterowania wytwarza odpowiednie sygnały sterujące. To jak IU dekoduje rozkazy jest dla nas nieistotne, ponieważ to jest zależne od danego procesora, a także jest to niejako "tajemnica" projektantów. Ze względu na stopień skomplikowania dekodera wyróżniamy architektury CISC oraz RISC. Przy czym prostszy, a zarazem szybszy dekoder jest zawarty w tej drugiej architekturze. Architektura RISC zawiera zwykle także mniejszą liczbę rozkazów.
  • AU oraz MMU - AU czyli jednostka adresująca (ang. Addresing Unit) jest de facto połączona z MMU, czyli układem zarządzania pamięcią (ang. Memory Management Unit). Odpowiadają one za poprawne obliczenie adresów w pamięci operacyjnej, a także za odpowiednie zarządzanie nią przez procesor. Dzięki tym układom CPU wie, jak dostać się do danych adresów w pamięci oraz jak obliczać położenie danej komórki.

Jednostka wykonawcza:

  • Rejestry - rejestry procesora (ang. registers). Wyjaśnienia poniżej
  • ALU razem z FPU - ten pierwszy układ to jednostka arytmetyczno-logiczna (ang. Arythmetic-logical Unit). Mogłeś sobie zadawać pytanie: "Jak procesor dodaje do siebie dwie liczby ?". To tutaj właśnie odbywają się wszystkie operacje matematyczne i logiczne. O ile ALU operuje jedynie na liczbach całkowitych o tyle FPU (ang. Floating Point Unit) zwany koprocesorem działa na liczbach zmiennoprzecinkowych. FPU ma swoje specjalne rozkazy poprzedzone literą "F" a także specyficzną budowę swoich własnych rejestrów, o czym dowiemy się później.

Rejestry procesora

edytuj

Tak naprawdę sam procesor nie wykonuje działań bezpośrednio na pamięci - byłoby to dość czasochłonne. Dlatego procesor dysponuje pewną określoną liczbą pamięci, przeznaczoną specjalnie dla niego. Ta pamięć to m.in. rejestry. To właśnie w nich przechowywane są dane, na których procesor wykona pewne działania np. w następnym rozkazie. Liczba rejestrów i ich przeznaczenie zależy od architektury procesora, lecz wśród nich możemy wyróżnić:

  • rejestry ogólnego przeznaczenia
  • rejestry kontrolne
  • rejestry segmentowe
  • rejestry wskaźnikowe
  • rejestry indeksowe

Należy pamiętać, że nie wszystkie rejestry są dostępne dla programistów. Niektóre jak na przykład rejestr PC ( ang. Program Counter), zwany potocznie licznikiem instrukcji czy rejestr wskaźnika instrukcji są sterowane i modyfikowane przez procesor. Nikt oprócz niego nie ma do tych elementów dostępu. Rejestry segmentowe służą do adresowania danych fragmentów pamięci operacyjnej, zaś indeksowe służą pomocą przy operacjach na ciągach bitów, bajtów, wszelkiej maści tablic etc. Jeśli nie będziesz pisał systemu operacyjnego, to raczej nie będziesz musiał korzystać z rejestrów kontrolnych - zwykle są one niedostępne dla procesów, działających w przestrzeni użytkownika, a ich użycie powoduje awaryjne zakończenie programu. Zatem, aby wykonać omówione wcześniej dodawanie procesor musi:

  1. skopiować liczbę z pamięci do rejestru
  2. skopiować drugą liczbę z pamięci do drugiego rejestru
  3. dodać obie liczby do siebie
  4. przenieść wynik obliczeń do któregoś z rejestrów
  5. skopiować wynik z rejestru do pamięci

Cykl rozkazowy

edytuj

Jak wspomnieliśmy procesor musi pobrać dany rozkaz, następnie go zdekodować (czyli jakby go sobie "przetłumaczyć"), a potem wykonać. Całość oczywiście wykonywana jest cyklicznie, z prędkością narzuconą przez zegar procesora. Całość cyklu można podzielić na dwie części: fazę pobrania oraz fazę wykonania. Faza pobrania polega na pobraniu kodu rozkazu z komórki pamięci o adresie przechowywanym w liczniku rozkazów, a następnie na umieszczeniu tego kodu w rejestrze rozkazów IR znajdującym się w układzie sterowania mikroprocesora. Kod rozkazu przesyłany jest do mikroprocesora magistralą danych. Następnie, zawartość rejestru wskaźnika instrukcji jest modyfikowana tak, aby wskazywał on na kolejny kod rozkazu przeznaczony do pobrania. Po zakończeniu fazy pobrania następuje faza wykonania. W tej fazie kod w rejestrze IR jest tłumaczony w dekoderze rozkazów, po czym generowane są odpowiednie sygnały sterujące zarówno wewnętrzne jak i zewnętrzne. Oto jak w przybliżeniu wykonują się poszczególne fazy:

  • Faza pobierania:
  1. Do magistrali adresowej umieszczany jest adres komórki w pamięci w której znajduje się rozkaz do wykonania.
  2. Zawartość tej komórki zostaje skopiowana do rejestru IR.
  3. Na koniec zostaje zwiększona wartość licznika instrukcji tak, aby pokazywał kolejny adres następnej instrukcji.

 


Obliczony przez procesor adres rozkazu w pamięci jest umieszczony na magistrali adresowej. Ten adres zostaje odebrany przez kontroler pamięci operacyjnej, który lokalizuje daną komórkę oraz kopiuje jej wartość i przesyła na magistralę danych. Tą swoistą "autostradą" pomiędzy procesorem a pamięcią, nasz rozkaz podąża do rejestru rozkazów gdzie czeka dalsze operacje.

  • Faza wykonania:
  1. Dany kod rozkazu zostaje przetłumaczony na postać zrozumiałą dla procesora, a następnie zostają wygenerowane odpowiednie sygnały sterujące. Teraz dany rozkaz jest wykonywany przez komputer.

Oczywiście jeśli dany rozkaz nie mieści się w jednej komórce to odpowiednie etapy fazy pobrania są powtarzane tak długo aż uzyska się kod całego rozkazu. Jak sobie wyjaśniliśmy, fazy są wykonywane jedna po drugiej, lecz wprowadzono technologię zwaną prefetching`iem. Dzięki tej modyfikacji już w trakcie wykonywania jednego rozkazu, pobierany jest następny. Najlepiej całą ideę ilustruje poniższy schemat:

 

Pamięć

edytuj

Drugim ważnym elementem komputera jest pamięć. Jest to swego rodzaju magazyn danych dla procesora. To tutaj składuje się zarówno sam kod maszynowy programu, jak i dane, które będą przetwarzane. Z punktu widzenia elektronika, pamięć składa się z bardzo dużej ilości kondensatorów, z których każdy odpowiada za 1 bit informacji. Ładunek o wyższym napięciu w kondensatorze oznacza 1, a o niższym oznacza 0. Zazwyczaj z pewną granicą, aby nie nastąpiła nieprawidłowa interpretacja danych. Przykładowo: od 0V do 0.7V - logiczne 0, od 1.5V wzwyż logiczne 1. Jest tak ponieważ zapewnia to dłuższą żywotność sprzętu.

Osiem bitów odpowiada jednemu bajtowi informacji. Dopiero bajt jest adresowalną jednostką informacji. Oznacza to, że procesor może odwoływać się tylko do pojedynczego bajtu pamięci, natomiast dostęp do konkretnego bitu możliwy jest dopiero za pomocą odpowiednich instrukcji logicznych procesora. Rozróżniamy różne rodzaje pamięci, takie jak RAM (pamięć przeznaczona do zapisu i odczyt) oraz ROM (wyłącznie odczyt, w niej zawarte są programy dzięki którym można zainicjować pracę komputera, jest to pamięć nieulotna). Ta część, która nas najbardziej w chwili obecnej interesuje to pamięć RAM. Można ją podzielić na dwa rodzaje:

  • Pamięć dynamiczna (DRAM) - jest dużo tańsza w produkcji i zarazem wolniejsza od pamięci statycznej, jednak znacznie od niej pojemniejsza. Z niej buduję się pamięć operacyjną dla zestawu komputerowego. Jest wolniejsza gdyż jak sama nazwa wskazuje jest dynamiczna. Oznacza to, że zawartość pamięci musi być co jakiś czas odświeżana. Polega to na cyklicznym zapisie informacji do komórek tej pamięci.
  • Pamięć statyczna (SRAM) - ma mniejsze zdolności scalania, zatem układy zbudowane z niej muszą być małe. Jest znacznie droższa i szybsza od pamięci dynamicznej. Z pamięci statycznej buduje się głównie pamięci podręczne (cache) procesora.

Urządzenia wejścia i wyjścia

edytuj

Działanie komputera nie miało by sensu, gdyby użytkownik nie mógł mu dostarczyć odpowiednich danych i uzyskać efektów działania komputera. Urządzeniami, które umożliwiają komunikację na linii użytkownik - komputer są tzw. urządzenia wejścia-wyjścia, w skrócie zwane urządzeniami I/O (z ang. Input/Output). Dostęp do nich umożliwiają osobne instrukcje procesora, lecz współcześnie, programista nie korzysta bezpośrednio z tych rozkazów. Najczęściej programista odwołuje się do systemu operacyjnego komputera, w którym zawarte są sterowniki urządzeń. To właśnie sterownik umożliwia programiście łatwy dostęp do urządzenia. Korzystając z funkcji systemu operacyjnego twórca oprogramowania nie musi w zasadzie znać działania tego sprzętu - wystarczy mu znajomość API samego systemu.