Procesor 8080:

Intel 8080 jest jednym z pierwszych mikroprocesorów, wyprodukowany przez Intela w kwietniu 1974. Jest 8-bitowym mikroprocesorem wykonanym w technologii n-MOS, pracującym z częstotliwością taktowania 2 MHz. Jest on uniwersalną jednostką centralną złożoną z jednostki arytmetyczno-logicznej, rejestrów roboczych i układu sterowania. Dane i instrukcje są przesyłane do i z pamięci za pośrednictwem 8-bitowej szyny danych, pamięć jest adresowana 16-bitową szyną adresową.

Żródło: http://pl.wikipedia.org/wiki/Intel_8080

W skrócie: Intel 8080 to procesor ośmiobitowy z szesnastobitowym adresowaniem pamięci. Szyna danych w takim procesorze jest ośmiobitowa, a szyna adresowa szesnastobitowa. Oznacza to, że maksymalnie na tym procesorze można zapisać 65536 bajtów pamięci. Jeden adres zapisywany w pamięci lub pobierany z niej wymaga dwóch odwołań do pamięci.

Czym jest mnemonik? Mnemonik jest niczym innym jak po prostu kodem rozkazu w formie czytelnej dla człowieka. Łatwiej jest przecież zapamiętać skróty typu MOV, ADD, SUB niż zupełnie nic nie znaczące kody szesnastkowe.

W tym momencie umówmy się co do jednej bardzo ważnej kwestii. Wszystkie liczby, o jakich będzie mowa w artykule, to liczby szesnastkowe, to znaczy, że np. po dodaniu ósemki do wartości 18 uzyskujemy 20. Ważne jest, żeby przyzwyczaić się do tego jak najszybciej.

Pierwszy program

Pierwszy program demonstruje użycie podprogramów w programowaniu procesorów na bazie 8080. Konieczne jest na początku ustawienie wskaznika stosu, najlepiej na koniec pamięci, gdyż stos zapełnia się "idąc" w dół pamięci. Skok do podprogramu umożliwia instrukcja CALL, wyjście z podprogramu RET. CALL jest to instrukcja, która pobiera parametr będący adresem komórki pamięci, od której procesor powinien kontynuować przetwarzanie. Aby możliwy był powrót z podprogramu, procesor musi odłożyc na stosie adres powrotu. Jest to adres kolejnej instrukcji zaraz po CALL. Instrukcja CALL zajmuje trzy bajty. Pierwszy to kod rozkazu, drugi to młodsza część adresu, trzeci starsza. Należy zapamiętać, że młodsza część adresu zawsze zapisywana/odczytywana jest przed starszą.

Przykładowy program wygląda tak:
Addr | Kod| Mnemonik
0000 | 31 | LXI SP 0400H
0001 | 00 | 
0002 | 04 |
0003 | CD | CALL 01AB
0004 | AB |
0005 | 01 | 
0006 | C3 | JMP
0007 | 03 |
0008 | 00 |
--------------------------
01AB | C9 | RET
--------------------------
03FE | ?? |
03FF | ?? |
Dlaczego dwie ostatnie pozycje są niewiadome i dlaczego są to akurat 03FE i 03FF? Otóż jest to końcówka stosu, dopóki nie odpalimy programu nie obchodzi nas co tam jest. Wskaźnik stosu ustawiliśmy na 0400. Oznacza to, że stos znajduje się poniżej tej wartości, tzn. 03FF, 03FE, 03FD itd. Prześledźmy po kolei przebieg powyższego programu. Komórki oznaczone na czerwono oznaczają zapis do pamięci, niebieskie adresy to adresy należące do stosu. Pogrubione wartości to adresy, pod które za chwilę procesor wykona skok.
   Addr | Kod| Mnemonik
   0000 | 31 | LXI SP 0400H
   0001 | 00 |
   0002 | 04 |
 ->0003 | CD | CALL 01AB
|  0004 | AB |
|  0005 | 01 |
|
|  03FF | 00 |
|
|  03FE | 06 |
|
|  01AB | C9 | RET
|
|  03FE | 06 |
|  03FF | 00 |
|
|  0006 | C3 | JMP
|  0007 | 03 |
|  0008 | 00 |
 --
Dla ułatwienia rozdzielilem od siebie miejsca, w których procesor "skacze po pamięci" tzn. przechodzi do innej komórki w pamięci niż kolejna po tej, którą pobrał/zapisał ostatnio.

Zauważmy, że adres powrotu czyli 0006 (adres kolejnej instrukcji po instrukcji CALL) odkładany jest na stosie w kolejności odwrotnej, tzn. od końca stosu. Dlatego też najpierw odkładana jest starsza część adresu, a potem młodsza. Dzięki temu w pamięci adres zapisany jest w kolejności młodsza -> starsza część. Dlaczego nie odkłada najpierw tej młodszej czesci? Ano dlatego, żeby wskaźnik stosu nie latał po pamięci, dzieki temu wskaźnik cały czas zmienia się tylko o jeden.

Jak łatwo zauważyć, program działa w pętli, a to co robi to skok do podprogramu i natychmiastowy z niego powrót. Kolejny program będzie podobny, z tym że zamiast wykorzystania rozkazu CALL i ręcznego wprowadzania adresu, do którego należy skoczyć, skorzystamy z rozkazów RST (RST0, RST1, itd.). Są to również instrukcje odpowiedzialne za skok do podprogramu, z tą różnicą, że adres podprogramu jest już zdefiniowany w kodzie rozkazu. Przykładowy program wykonuje trzy takie skoki do podprogramów, po czym kończy działanie.
Addr | Kod| Mnemonik
0000 | 31 | LXI SP 0400H
0001 | 00 |
0002 | 04 |
0003 | D7 | RST2
0004 | DF | RST3
0005 | E7 | RST4
0006 | 76 | HLT
--------------------------
0010 | C9 | RET
--------------------------
0018 | C9 | RET
--------------------------
0020 | C9 | RET
--------------------------
03FE | ?? |
03FF | ?? |
A tak wygląda przebieg realizacji tegoż programu:
Addr | Kod| Mnemonik
0000 | 31 | LXI SP 0400H
0001 | 00 |
0002 | 04 |
0003 | D7 | RST2

03FF | 00 |

03FE | 04 |

0010 | C9 | RET

03FE | 04 |
03FF | 00 |

0003 | DF | RST3

03FF | 00 |

03FE | 05 |

0018 | C9 | RET

03FE | 05 |
03FF | 00 |

0003 | E7 | RST4

03FF | 00 |

03FE | 06 |

0020 | C9 | RET

03FE | 06 |
03FF | 00 |

0006 | 76 | HLT
Poniżej ten sam program pokazujący bardziej obrazowo (czytaj: strzałeczkami) wszystkie skoki.


          Addr | Kod| Mnemonik
          0000 | 31 | LXI SP 0400H
          0001 | 00 |
          0002 | 04 |
    ------0003 | D7 | RST2
   |
   |      03FF | 00 |
   |      03FE | 04 |
   |
   |  ----0004 | DF | RST3 <-----
   | |                           |
   | |    03FF | 00 |            |
   | |    03FE | 05 |            |
   | |                           |
   | |  --0005 | E7 | RST4 <---  |
   | | |                       | |
   | | |  03FF | 00 |          | |
   | | |  03FE | 06 |          | |
   | | |                       | |
   | | |  0006 | 76 | HLT <--  | |
   | | |                     | | |
    -|-|->0010 | C9 | RET----|-|-
     | |                     | |
      -|->0018 | C9 | RET----|-
       |                     |
        ->0020 | C9 | RET----

          03FE | ?? |
          03FF | ?? |
Wspomniałem o tym, że adres skoku jest zapisany już w rozkazie, jednak nie napisałem jaki to adres. Otóż jest to X*8, gdzie X to numer przy instrukcji RST. Należy pamiętać, że do adresacji pamięci używamy tutaj wartości heksadecymalnych, zatem adres skoku dla RST2 to 2*8=10.

Tak jak poprzednio, pierwszą instrukcją jest ustawienie wskaźnika stosu na adres 0400. Następnie wykonywany jest rozkaz RST2 czyli skok do komórki 0010. W tej komórce znajduje się jedynie rozkaz powrotu z podprogramu. Program wykonuje takie skoki trzy razy (rozkaz RST2, RST3 i RST4), następnie procesor zatrzymuje się za sprawą rozkazu HLT.

Różnice między powyższymi programami.

Oba powyższe programy zawierały rozkazy odpowiedzialne za przejście do podprogramów. Zarówno CALL, jak i RST odkładają adres powrotu na stos i przenoszą sterowanie do podprogramu. Rozkaz CALL wymagał parametru, którym jest adres komórki pamięci, od której rozpoczyna się podprogram. Rozkazy RST mają tę zaletę, że nie wymagają podania owego adresu, ale mają go zapisanego na stałe. Wiążą się z tym pewne ograniczenia. Po pierwsze rozkazów takich mamy zaledwie 8, a każdy kolejny skacze do adresu o 8 większego. Jeśli zatem programista chciałby skorzystać ze wszystkich, każdy podprogram, który napisze (poza ostatnim) powinien mieścić się w ośmiu bajtach.

Cykl rozkazowy a cykl maszynowy.

Układ DMA umożliwia podgląd realizacji programu zatrzymując się przy każdym cyklu rozkazowym lub maszynowym. Na powyższych programach łatwo opisać różnicę. Otóż cykl rozkazowy trwa od jednego zapisanego mnemoniku do następującego po nim (oczywiście nie wliczając jeszcze tego drugiego). Wszystkie wiersze bez mnemoniku należą do cyklu rozkazowego rozpoczętego ostatnim wierszem z mnemonikiem (dziwnie opisałem, ale każdy powinien zrozumieć). Ponadto do cyklu rozkazowego należą odwołania do pamięci związane z odkładaniem lub pobieraniem adresu na stos.

Cykl maszynowy natomiast to cykl, podczas którego następuje jednokrotne odwołanie do pamięci. W przypadku powyższych programów jest to po prostu każdy wiersz kodu. Pamiętajmy, że jest to każde odwołanie do pamięci, włączając w to odkładanie czy pobieranie wartości na stos. Przykładowo rozkaz CALL nie potrzebuje trzech cyklów maszynowych na wykonanie (co mogłyby sugerować zajmowane przez niego 3 bajty), ale aż pięciu, gdyż zapis adresu powrotu na stos to dodatkowe dwa odwołania do pamięci.

Obsługa przerwań.

Większość współczesnych mikroprocesorów obsługuje przerwania, jednak zwykle są one domyślnie zablokowane. Poniższy program ma na celu pokazać

  Na górę

© Designed by htmltemplates.net

html templates website templates