Serwis Edukacyjny w I-LO w Tarnowie ![]() Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2023 mgr Jerzy Wałaszek |
SPIS TREŚCI |
|
Podrozdziały |
Procesor PMC II pobiera kolejne instrukcje z pamięci (przy pomocy licznika programu) i umieszcza je w rejestrze instrukcji. Pobrana instrukcja jest analizowana w celu określenia rodzaju operacji do wykonania. Po rozkodowaniu instrukcji procesor wykonuje wskazane polecenie i pobiera kolejną instrukcję.
Aby zrozumieć kodowanie rozkazów w PMC II musimy przedstawić instrukcję w postaci binarnej - czyli tak, jak jest ona przechowywana wewnątrz komputera. Ponieważ instrukcje są umieszczane w 16 bitowych komórkach pamięci PMC II, to każda z nich zbudowana jest z 16 bitów. Bity te podzielimy na trzy grupy, które będziemy zwać polami (ang. bit field).
Bity instrukcji PMC II | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b15 | b14 | b13 | b12 | b11 | b10 | b9 | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
Pole instrukcji | Pole trybu adreso- wania |
Pole argumentu |
Bity b12...b15 (cztery najstarsze) tworzą pole instrukcji. Od kombinacji bitów w tym polu zależy rodzaj instrukcji, czyli rodzaj operacji, które wykona procesor po rozkodowaniu instrukcji. Cztery bity pozwalają na 16 różnych kombinacji i tyle różnych instrukcji może wykonać procesor PMC II.
Dwa następne bity b10 i b11 określają tzw. tryb adresowania. Tryb adresowania jest sposobem pobierania przez procesor argumentu dla instrukcji. Dwa bity pozwalają na cztery różne tryby adresowania.
Pozostałe bity b0...b9 określają argument dla instrukcji. Ich dokładne znaczenie zależy od zawartości pola trybu adresowania.
Procesor PMC II potrafi pobierać argument dla rozkazu na cztery różne sposoby. Rodzaj adresowania zapisany jest w postaci dwubitowego kodu w polu tryby adresowania instrukcji PMC II. W zależności od kombinacji tych bitów rozróżniamy następujące tryby adresowania:
|
Tryb adresowania akumulatora. Argument dla instrukcji znajduje się w rejestrze akumulatora. |
||||
|
Tryb adresowania
natychmiastowy. Argument znajduje się w bitach od b0...b9 kodu instrukcji. Bity te są traktowane jako liczba w kodzie U2 (jeśli nie wiesz, co to jest liczba w kodzie U2, to musisz przeczytać odpowiedni rozdział w artykule Binarne Kodowanie Liczb). Ponieważ bitów tych jest 10, to możliwe wartości argumentu w trybie natychmiastowym zawierają się w granicach od -512 do 511. |
||||
|
Tryb adresowania bezpośredni Argument znajduje się w komórce pamięci, której adres przechowują bity b0...b5 kodu instrukcji. Pozostałe bity pola argumentu są ignorowane. Jeśli adres wynosi 0, to argument jest w rejestrze INOUT. |
||||
|
Tryb pośredni Bity b0...b5 kodu instrukcji zawierają adres komórki pamięci, która przechowuje adres właściwego argumentu. Stąd nazwa tryb pośredni - w instrukcji wskazujemy komórkę zawierającą właściwy adres argumentu. Taki tryb znakomicie nadaje się do adresowania danych umieszczonych w tablicy, ponieważ w prosty sposób można zmieniać adres zawarty w komórce. |
Wszystkie podane tryby adresowania argumentu mogą być stosowane z każdą instrukcją PMC II (chociaż nie zawsze ma to sens).
Rodzaj instrukcji do wykonania określa 4-bitowe pole instrukcji. Instrukcje są następujące:
|
END arg Instrukcja powoduje zakończenie wykonywania przez PMC II programu. Argument jest pobierany i zwracany jako wynik instrukcji END (pojawia się w okienku informacyjnym). Po wykonaniu tej instrukcji program może być uruchomiony jedynie od nowa - nie ma możliwości kontynuacji. |
||||||||
|
LDA arg LoaD Accumulator Instrukcja pobiera podany argument do rejestru akumulatora. |
||||||||
|
STA arg STore Accumulator Instrukcje umieszcza zawartość akumulatora w podanym argumencie. Jeśli argument jest adresowany przez tryb 0 lub 1 (akumulatora lub natychmiastowy), to instrukcja nic nie robi. |
||||||||
|
ADD arg Instrukcja dodaje do akumulatora podany argument. Wynik operacji arytmetycznej i logicznej zawsze jest umieszczany w akumulatorze. Jeśli argument jest adresowany przez tryb 0 (tryb akumulatora), to w wyniku zawartość akumulatora ulegnie podwojeniu. Instrukcja nie sprawdza, czy wynik operacji mieści się w |
||||||||
|
SUB arg SUBstract Instrukcja odejmuje od akumulatora podany argument. Jeśli argument jest adresowany przez tryb 0, to w wyniku otrzymujemy 0. Jeśli wynik operacji przekracza zakres 16 bitowych liczb U2, to zostaje obcięty do 16 bitów. |
||||||||
|
MUL arg MULtiply Instrukcja mnoży zawartość akumulatora przez podany argument. Jeśli argument jest adresowany przez tryb 0, to w wyniku otrzymujemy kwadrat poprzedniej zawartości akumulatora. Wynik mnożenia jest zawsze obcinany do 16 bitów w kodzie U2. |
||||||||
|
DIV arg DIVide Instrukcja dzieli zawartość akumulatora przez podany argument. Jeśli argument jest adresowany przez tryb 0, to wynik wynosi 1. Jeśli argument ma wartość 0, to powstaje błąd dzielenia przez 0 i wykonanie programu zostaje zatrzymane z wyświetleniem odpowiedniego komunikatu. |
||||||||
|
MOD arg MODulo Instrukcja oblicza wartość reszty z dzielenia akumulatora przez podany argument. Jeśli argument jest adresowany przez tryb 0, to wynik wynosi 0. Jeśli argument jest równy 0, to powstaje błąd dzielenia przez 0 i wykonanie programu zostaje wstrzymane z wyświetleniem odpowiedniego komunikatu. |
||||||||
|
INC arg INCrement Instrukcja zwiększa o 1 podany argument. Jeśli argument jest adresowany przez tryb 1 (tryb natychmiastowy), instrukcja nic nie robi. Jeśli wynik operacji przekracza zakres 16-bitowych liczb U2, zostanie obcięty do 16 bitów. |
||||||||
|
DEC arg DECrement Instrukcja zmniejsza o 1 podany argument. Jeśli argument jest adresowany przez tryb 1 (tryb natychmiastowy), instrukcja nic nie robi. Jeśli wynik operacji przekracza zakres 16-bitowych liczb U2, zostanie obcięty do 16 bitów. |
||||||||
|
JMP arg JuMP Instrukcja skoku pod adres równy podanemu argumentowi. Wykonanie tej instrukcji polega na umieszczeniu wartości argumentu w rejestrze licznika rozkazów. Dzięki temu następna instrukcja zostanie wykonana nie z następnego adresu, lecz z nowego. Instrukcje skoku umożliwiają tworzenie tzw. pętli oraz rozgałęzień w programie. Chociaż instrukcja może być stosowana z dowolnym trybem adresowania, jednak najczęściej jest stosowany tryb natychmiastowy - adres skoku znajduje się bezpośrednio w bitach pola argumentu instrukcji. |
||||||||
|
JZR
arg Jump on ZeRo Instrukcja wykonuje skok pod adres wskazany argumentem tylko wtedy, gdy akumulator zawiera wartość zero. W przeciwnym razie skok nie zostanie wykonany - następną instrukcją dla procesora będzie instrukcja za rozkazem skoku. Tego typu operacja nazywana jest skokiem warunkowym (ang. conditional jump). |
||||||||
|
JMI arg Jump on MInus Instrukcja wykonuje sok pod adres wskazany argumentem tylko wtedy, gdy akumulator zawiera wartość ujemną. W przeciwnym razie skok nie zostanie wykonany i procesor przejdzie do instrukcji znajdującej się za rozkazem skoku. |
||||||||
|
AND arg Instrukcja wykonuje operację logiczną AND na bitach akumulatora i argumentu. Wynik jest umieszczany w akumulatorze. (Jeśli nic nie wiesz na temat operacji logicznych, to przeczytaj artykuł o Binarnym Kodowaniu Liczb). |
||||||||
|
ORA arg OR with Accumulator Instrukcja wykonuje operację logiczną OR na bitach akumulatora i argumentu. Wynik jest umieszczany w akumulatorze. |
||||||||
|
XOR arg eXclusive OR Instrukcja wykonuje operację logiczną XOR na bitach akumulatora i argumentu. Wynik jest umieszczany w akumulatorze. |
Dla przykładu zakodujmy w postaci binarnej instrukcję, która dodaje do zawartości akumulatora liczbę 15. Kod instrukcji dodawania, to 0011. W ten sposób określamy bity pola kodu instrukcji. Liczba 15 jest daną natychmiastową, zatem pole trybu adresowania ma kod 01. Pozostałe dziesięć bitów określa w kodzie U2 liczbę 15 - 0000001111. Łączymy poszczególne pola w całość i otrzymujemy:
0011010000001111 - dodaj do akumulatora liczbę 15. Proste?
Ponieważ zapis bitowy instrukcji PMC II jest niewygodny, każda instrukcja posiada 3 literową nazwę, którą nazywamy mnemonikiem. Mnemonik ułatwia zapamiętanie polecenia. W poniższej tabeli zebraliśmy wszystkie instrukcje PMC II
Mnemonik | Pole instrukcji | Krótki opis |
---|---|---|
END arg |
0000 | Koniec programu |
LDA arg |
0001 | AC ← arg, PC ← PC + 1 |
STA arg |
0010 | arg ← AC, PC ← PC + 1 |
ADD arg |
0011 | AC ← AC + arg, PC ← PC + 1 |
SUB arg |
0100 | AC ← AC - arg, PC ← PC + 1 |
MUL arg |
0101 | AC ← AC x arg, PC ← PC + 1 |
DIV arg |
0110 | AC ← AC : arg, PC ← PC + 1 |
MOD arg |
0111 | AC ← AC MOD arg, PC ← PC + 1 |
INC arg |
1000 | arg ← arg + 1, PC ← PC + 1 |
DEC arg |
1001 | arg ← arg - 1, PC ← PC + 1 |
JMP arg |
1010 | PC ← arg |
JZR arg |
1011 | Jeśli AC = 0, PC ← arg, inaczej PC ← PC + 1 |
JMI arg |
1100 | Jeśli AC < 0, PC ← arg, inaczej PC ← PC + 1 |
AND arg |
1101 | AC ← AC AND arg, PC ← PC + 1 |
ORA arg |
1110 | AC ← AC OR arg, PC ← PC + 1 |
XOR arg |
1111 | AC ← AC XOR arg, PC ← PC + 1 |
Oprócz rozkazów dla procesora PMC II zdefiniowana jest
jeszcze tzw, dyrektywa DAT, która umożliwia umieszczenie danych w komórce
pamięci. Dyrektywa nie jest rozkazem i nie zostaje przetłumaczona na kod
instrukcji. Zamiast tego w bieżącej komórce umieszcza się argument tej
dyrektywy. Argument może być liczbą 16-bitową U2 o
zakresie od
DAT 115 ;umieszczenie w komórce liczby 115
PMC II posiada 4 tryby adresowania argumentu.
Tryb adresowania akumulatora tworzymy nie umieszczając za instrukcją żadnych danych. Na przykład
ADD
|
Oznacza dodanie do siebie zawartości rejestru akumulatora.
Uwaga - jeśli zastosujemy rozkaz skoku JMP, JZR lub JMI bez argumentu, to PMC II wykona skok pod adres zawarty w akumulatorze. Czasami może to być potrzebne (tzw. skoki wyliczane).
W tym trybie wartość argumentu jest bezpośrednio zakodowana w bitach pola argumentu. Tryb natychmiastowy oznaczamy umieszczając bezpośrednio przed wartością znak #. Na przykład:
LDA #15 |
oznacza polecenie umieszczenia w akumulatorze liczby 15. Po wykonaniu tej instrukcji akumulator będzie zawierał wartość 15. Inne przykłady:
ADD #8 ;dodanie do zawartości akumulatora liczby 8 MUL #5 ;pomnożenie akumulatora przez 5 |
Tryb natychmiastowy stosowany jest standardowo z rozkazami skoków:
JMP #26 ;skok do instrukcji umieszczonej pod adresem 26 |
Pole argumentu zawiera w tym trybie adres komórki pamięci PMC II, w której jest właściwy argument. Tryb bezpośredni oznaczamy umieszczając bezpośrednio przed adresem znak $. Na przykład:
LDA $15 |
oznacza polecenie umieszczenia w akumulatorze zawartości komórki pamięci PMC II o adresie 15. Zwróć uwagę, iż nie jest to to samo co poprzednio, ponieważ komórka 15 może zawierać dowolną wartość. Inne przykłady:
STA $0 ;umieść zawartość akumulatora w rejestrze INOUT STA $10 ;umieść zawartość akumulatora w komórce pamięci pod adresem 10 ADD $5 ;dodaj do zawartości akumulatora zawartość komórki pod adresem 5 |
Zapamiętaj dobrze różnicę pomiędzy trybem natychmiastowym, a bezpośrednim. W trybie natychmiastowym argument jest bezpośrednio podany w instrukcji. W trybie bezpośrednim w instrukcji podajemy adres komórki zawierającej argument:
MUL #6 ;mnóż akumulator przez liczbę 6 MUL $6 ;mnóż akumulator przez to, co zawiera komórka o adresie 6 |
W trybie tym instrukcja w polu argumentu zawiera adres komórki przechowującej właściwy adres argumentu. Dostęp do argumentu jest zatem pośredni poprzez wskazywaną komórkę. Tryb pośredni oznaczamy umieszczając bezpośrednio przed adresem komórki znak *:
LDA *15 |
Instrukcja ta oznacza pobranie do akumulatora zawartości komórki pamięci PMC II, której adres przechowuje komórka o adresie 15. Jeśli przykładowo w komórce tej jest liczba 25, to do akumulatora trafi zawartość komórki o adresie 25.
Tryb pośredni jest najtrudniejszym do zrozumienia trybem adresowania, lecz z drugiej strony najczęściej się go stosuje przy dostępie do tablic. Zapamiętaj, iż w trybie pośrednim instrukcja zawiera adres komórki, w której jest właściwy adres argumentu.
Posługiwanie się adresami liczbowymi jest dosyć żmudne i nużące. Dlatego programiści wymyślili etykiety. Etykieta jest nazwą, którą dużo łatwiej zapamiętać. W PMC II etykiety muszą rozpoczynać się od litery lub od znaku podkreślenia. Następne znaki muszą być literami, cyframi lub znakami podkreślenia. Tylko pierwsze 8 znaków etykiety jest znaczące. Etykieta musi się kończyć znakiem dwukropka.
Etykiety umieszcza się zawsze przed instrukcją lub przed dyrektywą DAT. Etykieta przyjmuje wartość adresu instrukcji, przy której została umieszczona. Umożliwia to później łatwiejsze wykonanie skoku do wybranej instrukcji lub odwołanie się do danych. Na przykład poniższy program sumuje dwie komórki i wynik umieszcza w trzeciej komórce.
Wersja bez etykiet
DAT 10 ;pierwsza liczba DAT 15 ;druga liczba DAT 0 ;tutaj będzie wynik dodawania LDA $1 ;pobieramy do akumulatora pierwszą liczbę ADD $2 ;dodajemy do niej drugą liczbę STA $3 ;wynik umieszczamy w trzeciej komórce END |
Wersja z etykietami
L1: DAT 10 ;pierwsza liczba L2: DAT 15 ;druga liczba WYNIK: DAT 0 ;tutaj będzie wynik dodawania START: LDA $L1 ;pobieramy do akumulatora pierwszą liczbę ADD $L2 ;dodajemy do niej drugą liczbę STA $WYNIK ;wynik umieszczamy w trzeciej komórce END |
Program jest zawsze umieszczany w pamięci PMC II począwszy od komórki o adresie 1. Zatem pierwsza instrukcja programu zawsze znajduje się w komórce o adresie 1. Bez etykiet musimy sami pamiętać, w których komórkach są dane i instrukcje. Z etykietami zadanie to mamy rozwiązane w prosty sposób. Do komórek będziemy się odwoływać za pomocą symbolicznych etykiet, zatem nie musimy nawet wiedzieć, pod którym adresem dana komórka się znajduje - zadanie to przejmuje za nas asembler, który tłumaczy tekst programu PMC II na odpowiednią zawartość komórek pamięci.
Jako dane w instrukcjach PMC II można stosować:
DAT 1745 DAT -15 LDA #33 STA $25 ADD *12 |
DAT 0FFFFH DAT 35AH AND #3FH STA $4CH |
Liczby szesnastkowe (jeśli nic nie wiesz o liczbach szesnastkowych, ósemkowych i binarnych, przeczytaj artykuł o Binarnym Kodowaniu Liczb) kończą się zawsze literką H. Jeśli liczba szesnastkowa rozpoczyna się od cyfry A,B,C,D,E lub F, to cyfrę tę należy poprzedzić cyfrą 0 - w przeciwnym razie asembler będzie sądził, iż jest to etykieta i powstanie błąd.
DAT 777Q DAT 33Q DIV #45Q |
Liczby ósemkowe kończą się zawsze literą Q.
DAT 1100101B DAT 1100B AND #11110000B |
Liczby dwójkowe zawsze kończą się literą B.
DAT "H DAT "A LDA #"B |
Znak jest zawsze poprzedzony cudzysłowem. Znak zostaje zamieniony na kod ASCII i w takiej postaci jest umieszczany w pamięci lub w kodzie instrukcji. Z kilku znaków tylko pierwszy jest znaczący:
LDA #"ABC ;w akumulatorze znajdzie się kod ASCII litery A |
DAT TEKST DAT DANE LDA $CZYNNIK JMP #START |
Jako dane można również stosować etykiety. Wartością etykiety jest zawsze adres komórki, do której etykieta się odnosi.
Tworząc program dla PMC II musimy przestrzegać kilku prostych zasad.
W programie można wstawiać dowolną ilość wierszy pustych (w przykładzie wiersz pusty pomiędzy etykietami LICZNIK oraz START):
LICZNIK: DAT 0 START: LDA $LICZNIK ... |
Wiersze puste nie są tłumaczone na zawartość pamięci, nie wpływają zatem na długość programu wynikowego.
Komentarz w PMC II rozpoczyna się od znaku średnika, po którym możemy umieścić dowolny tekst. Tekst ten nie jest analizowany przez asembler. Komentarze można umieszczać w dowolnym miejscu wiersza. Od początku komentarza do końca wiersza programu treść jest ignorowana. Komentarze są doskonałym narzędziem do dokumentowania działania programu.
;Zmienne programu PRCNT: DAT 10 ;wartość procentu KONTO: DAT 120 ;stan konta |
Jeśli wiersz ma definiować etykietę, to musi się ona znajdować na początku wiersza:
LP1: LDA $LICZNIK ADD #23 STA $LICZNIK JMI #LP1 |
Jeśli w wierszu umieścimy samą etykietę, to definiuje ona pierwszą komórkę z instrukcją, która wystąpi w najbliższym wierszu:
START: LDA $XXX ... |
W tym przykładzie etykieta START wskazuje komórkę z instrukcją LDA $XXX. Nie wolno definiować więcej niż jednej etykiety dla tej samej komórki.
Początkowe spacje są nieznaczące, zatem można je wykorzystywać do pozycjonowania instrukcji programu w tej samej pionowej kolumnie, co znakomicie poprawia czytelność. Porównaj dwa przykłady tego samego programu bez wcięć i z wcięciami. Który jest bardziej estetyczny i czytelny?
WSP_A: DAT -5 WSP_B: DAT 3 X: DAT 0 START: LDA $WSP_B JZR #KONIEC LDA $WSP_A DIV $WSP_B STA $X KONIEC: END |
WSP_A: DAT -5 WSP_B: DAT 3 X: DAT 0 START: LDA $WSP_B JZR #KONIEC LDA $WSP_A DIV $WSP_B STA $X KONIEC: END |
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2023 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.