Zadanie 3 (termin oddania: 1 grudnia 2005, godz. 23:59)

Zrealizuj symulator pewnego procesora. Ma on wczytać z wejścia
jeden wiersz zawierający program dla procesora, a następnie
wykonać go, wczytując ewentualne dane z wejścia oraz
wypisując wyniki na wyjście.

Procesor ma 10 rejestrów 10 bitowych przechowujących wartości
całkowite w kodzie U2 oraz dwa jednobitowe znaczniki mówiące
o tym, czy wynik ostatniej operacji był ujemny oraz czy był
zerem. W chwili rozpoczęcia rejestry są wyzerowane, znacznik
"zero" ustawiony jest na true, a "minus" na false.

Program na nasz procesor jest reprezentowany przez ciąg znaków
(napis). Każda z 10 rozpoznawanych przez procesor instrukcji
ma swój jednoliterowy kod, po którym podajemy od 0 do 2
jednoznakowych argumentów.

Poniżej znajduje się lista instrukcji wraz z opisem znaczenia.
W opisie tym R oraz S oznaczają numer rejestru ('0'..'9'),
D oznacza liczbę składającą się z jednej cyfry dziesiętnej a
NN to dwucyfrowy zapis liczby całkowitej, w którym pierwsza
cyfra (dziesiętna) jest bardziej znacząca, a druga mniej.

rR  (read)          - read(R)
wR  (write)         - writeln(R)
aRS (add)           - R:=R+S
cRS (copy)          - R:=S
nR  (negate)        - R:=-R
lRD (load)          - R:=D
jNN (jump)          - goto NN
mNN (jump if minus) - if minus then goto NN
zNN (jump if zero)  - if zero then goto NN
d   (dump)          - wypisuje zawartość rejestrów

Znaczniki "minus" i "zero", wykorzystywane w instrukcjach skoku
warunkowego 'm' i 'z' są aktualizowane po każdej instrukcji,
która przyjmuje jako argument przynajmniej jeden rejestr (czyli
po 'r' 'w' 'a' 'c' 'n' 'l') na podstawie wartości, która
znalazła się w tym rejestrze (gdy argumentem są dwa rejestry,
znaczniki opisują zawartość pierwszego z nich).

Program podczas działania procesora jest przechowywany w pamięci.
Komórki pamięci są adresowane kolejnymi liczbami naturalnymi
zaczynając od 1. Każda instrukcja zajmuje w pamięci od 1 do 3
komórek, np. instrukcja 'd' zajmuje jedna komórkę, 'r0' dwie
a 'c01' trzy.

Wykonanie programu rozpoczyna się od instrukcji znajdującej się
pod adresem 1, kończy się, gdy kolejnej instrukcji, którą
mielibyśmy wykonać, w programie nie ma.

Oto przykłady programów:

r0r1r2w2w1w0

   wczytuje trzy liczby i wypisuje je w kolejnosci odwrotnej,

r0r1c20a21c31n3a30l41a40d

   wczytuje dwie liczby, oblicza ich sumę, różnicę i dodaje 1
   do pierwszej liczby, na koniec pokazuje zawartość rejestrów,

r0w0l11n1a01z99j03

   wczytuje liczbę n>0 i wypisuje n..1,

r0r1c20c31n3a23z36m28c02j05c12n1j05w0

   wczytuje dwie liczby i wypisuje ich największy wspólny
   dzielnik,

r0r1r2c31c40n4a34z44w2c32a34z37w0j57w1w0j99c32a34z99w0w2w1

   wczytuje trzy liczby i wypisuje je tak, by równe ze sobą
   nie sąsiadowały. Jeśli to niemożliwe, nie wypisuje nic.

Postać danych:

Na wejściu znajduje się wiersz z programem (maksymalnie 100
znaków) oraz, w kolejnych wierszach, liczby będące danymi dla
symulowanego programu (po jednej w wierszu).

Postać wyniku:

Na wyjściu powinien się pojawić efekt wykonania instrukcji
'w' i 'd'.

Instrukcja 'w' wypisuje w zapisie dziesiętnym (chodzi o zwykłe
użycie Pascalowej instrukcji 'writeln'), w pojedynczym wierszu,
wartość argumentu. Instrukcja 'd' wypisuje zawartość rejestrów.
Dla każdego z dziesięciu rejestrów wypisujemy po jednym wierszu
zawierającym najpierw 10 cyfr binarnych wartości przechowywanej
w tym rejestrze (w kolejności od najbardziej znaczących),
następnie jedną spację oraz zapis dziesiętny tej wartości.