Asembler PMC II


Podrozdziały

 

Asembler jest częścią symulatora PMC II, która zamienia tekst programu zapisanego w postaci symbolicznej na program, który zostanie umieszczony w pamięci. Poniżej opisujemy budowę instrukcji PMC II oraz składnię wierszy programu.

 

Budowa instrukcji PMC II

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.

 

Tryby adresowania procesora PMC II

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:

 

b11 b10
0 0
Tryb adresowania akumulatora.

Argument dla instrukcji znajduje się w rejestrze akumulatora.

 

b11 b10
0 1
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.

b11 b10
1 0
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.
 

b11 b10
1 1
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).

 

Instrukcje procesora PMC II

Rodzaj instrukcji do wykonania określa 4-bitowe pole instrukcji. Instrukcje są następujące:

 

b15 b14 b13 b12
0 0 0 0
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.
 

b15 b14 b13 b12
0 0 0 1
LDA  arg

LoaD Accumulator

Instrukcja pobiera podany argument do rejestru akumulatora.
 

b15 b14 b13 b12
0 0 1 0
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.

b15 b14 b13 b12
0 0 1 1
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 16-bitowym zakresie liczb U2. Jeśli zakres zostanie przekroczony, to wynik jest zawsze obcinany do 16 bitów - w rezultacie może powstać błędna wartość sumy. Zagadnienia te są dokładnie opisane w artykule o Binarnym Kodowaniu Liczb.

b15 b14 b13 b12
0 1 0 0
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.

b15 b14 b13 b12
0 1 0 1
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.

b15 b14 b13 b12
0 1 1 0
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.

b15 b14 b13 b12
0 1 1 1
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.

b15 b14 b13 b12
1 0 0 0
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.

b15 b14 b13 b12
1 0 0 1
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.

b15 b14 b13 b12
1 0 1 0
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.

b15 b14 b13 b12
1 0 1 1
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).

b15 b14 b13 b12
1 1 0 0
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.

b15 b14 b13 b12
1 1 0 1
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).
 

b15 b14 b13 b12
1 1 1 0
ORA  arg

OR with Accumulator

Instrukcja wykonuje operację logiczną OR na bitach akumulatora i argumentu. Wynik jest umieszczany w akumulatorze.
 

b15 b14 b13 b12
1 1 1 1
XOR  arg

eXclusive OR

Instrukcja wykonuje operację logiczną XOR na bitach akumulatora i argumentu. Wynik jest umieszczany w akumulatorze.

 

Przykład:

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?

 

Mnemoniki instrukcji PMC II

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,  PCPC + 1
STA arg
0010 arg ← ACPCPC + 1
ADD arg
0011 ACAC + arg,  PCPC + 1
SUB arg
0100 ACAC - arg,  PCPC + 1
MUL arg
0101 ACAC x arg,  PCPC + 1
DIV arg
0110 ACAC : arg,  PCPC + 1
MOD arg
0111 AC ←  AC MOD arg,  PCPC + 1
INC arg
1000 arg ← arg + 1,  PCPC + 1
DEC arg
1001 arg ← arg - 1, PCPC + 1
JMP arg
1010 PC ← arg
JZR arg
1011 Jeśli AC = 0, PC ← arg, inaczej PCPC + 1
JMI arg
1100 Jeśli AC < 0, PC ← arg, inaczej PCPC + 1
AND arg
1101 ACAC AND arg,  PCPC + 1
ORA arg
1110 ACAC OR arg,  PCPC + 1
XOR arg
1111 ACAC XOR arg,  PCPC + 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 -32768 do 32767.
 

DAT 115 ;umieszczenie w komórce liczby 115

Oznaczenia trybów adresowania PMC II

PMC II posiada 4 tryby adresowania argumentu.
 

Tryb adresowania akumulatora

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).

 

Tryb natychmiastowy

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

Tryb bezpośredni

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

Tryb pośredni

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.

 

Etykiety

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.

 

Dane

Jako dane w instrukcjach PMC II można stosować:

 

Liczby dziesiętne

 

DAT 1745
DAT -15
LDA #33
STA $25
ADD *12

 

Liczby szesnastkowe

 

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.

 

Liczby ósemkowe

 

DAT 777Q
DAT 33Q
DIV #45Q

 

Liczby ósemkowe kończą się zawsze literą Q.

 

Liczby dwójkowe

 

DAT 1100101B
DAT 1100B
AND #11110000B

 

Liczby dwójkowe zawsze kończą się literą B.

 

Znaki

 

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

 

Etykiety

 

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.

 

Budowa wiersza programu PMC II

Tworząc program dla PMC II musimy przestrzegać kilku prostych zasad.

 

Wiersz pusty

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

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

 

Etykieta

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.

 

Wcięcia

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

 

Zadania

  1. Skąd pobiera procesor instrukcje wykonywanego programu?
  2. Co to jest pole bitowe?
  3. Z jakich pól bitowych składa się instrukcja PMC II? Jakie jest ich przeznaczenie?
  4. Co to jest asembler?
  5. Co to jest tryb adresowania?
  6. Czym różni się tryb adresowania natychmiastowego od trybu adresowania bezpośredniego?
  7. W jaki sposób w asemblerze PMC II oznaczamy podstawowe tryby adresowania?
  8. Co oznacza zapis asemblera: ADD *5 ?
  9. Do czego stosowane są etykiety?
  10. Jakie są reguły tworzenia etykiet?
  11. Jak zapisujemy w asemblerze PMC II liczby dziesiętne, binarne, ósemkowe i szesnastkowe?
  12. Co zostanie umieszczone w akumulatorze po wykonaniu instrukcji LDA #"1?
  13. Do czego wykorzystywane są komentarze?
  14. Uporządkuj wiersz wg kolejności składników: ;dodajemy #15 PUNKT1: ADD
  15. Dlaczego w PMC II procesor rozróżnia tylko 16 instrukcji?
  16. Co się stanie, jeśli w programie umieścimy samą instrukcję JMP?
     


List do administratora Serwisu Edukacyjnego Nauczycieli I LO

Twój email: (jeśli chcesz otrzymać odpowiedź)
Temat:
Uwaga: ← tutaj wpisz wyraz  ilo , inaczej list zostanie zignorowany

Poniżej wpisz swoje uwagi lub pytania dotyczące tego rozdziału (max. 2048 znaków).

Liczba znaków do wykorzystania: 2048

 

W związku z dużą liczbą listów do naszego serwisu edukacyjnego nie będziemy udzielać odpowiedzi na prośby rozwiązywania zadań, pisania programów zaliczeniowych, przesyłania materiałów czy też tłumaczenia zagadnień szeroko opisywanych w podręcznikach.



   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2017 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.