2008 03 Wojny rdzeniowe [Progra Nieznany


Programowanie

Programowanie

Wojny Rdzeniowe

Wojny Rdzeniowe

Wojny rdzeniowe

Marek Sawerwain

Wojny rdzeniowe – CoreWars – to legenda informatyki. Po raz pierwszy wzmianka o CoreWars pojawiła się w roku 1984 na The University of Western Ontario w Kanadzie. Jeden z autorów, A. K. Dewdney, napisał także kilka artykułów na ten temat do czasopisma Scientific American. W ten sposób narodziła się jedna z legend informatyki.

.pl

Wojny rdzeniowe to bardzo specyficzna maszyny MARS. Istnieje wiele dostępnych programów, gra, gdzie w pamięci zwanej rdzeniem oficjalnym programem jest pMars, który omawiam w tym (ang. core), zarządzanej przez komputer artykule. Innym równie ciekawym jest program o wszyst-software.com

albo procesor o nazwie MARS wykony- ko mówiącej nazwie CoreWars. Program ten oferuje na-linux@

wany jest kod umieszczonych w pamięci programów. Wy- wet dwie wersje języka programowania dla wojen rdze-grywa ten program, który pokona pozostałych przeciwników niowych: oryginalny RedCode oraz równie ciekawą jak np.: poprzez ich wymazanie z pamięci albo poprzez zastąpie- sam RedCode odmianę o nazwie CoreWars. Jednak, z ra-niem własnym kodem. Mówiąc inaczej, wygrywa ten pro- cji ograniczonego miejsca, będziemy zajmować się tylko gram, który nadal działa, po upłynięciu odpowiedniego cza- samym RedCode i środowiskiem MARS.

su. Programy dla systemu MARS są tworzone w języku o na-

zwie RedCode. Jest on bardzo podobny do assemblera. Ist- MARS – definicja

nieją kilka wariantów RedCode, jednak w dalszej części sku- Programy napisane w języku RedCode są wykonywane w ra-pimy się tylko na oryginalnej wersji RedCode.

mach ściśle określonego środowiska. Głównym elementem

Skromne ramy artykułu pozwalają na przedstawienie tego środowiska jest pamięć operacyjna, czyli rdzeń. Zazwy-tylko kilku przykładów. Dlatego już na samym początku czaj do dyspozycji mamy 8000 dostępnych komórek pamię-

zachęcam na szukania innych przykładów programów pi- ci. Ilość pamięci można zmieniać, a ogólnie wielkość pamię-

sanych w RedCode. Warto także na samym początku po- ci jest zapisana w przedefiniowanej zmiennej CORESIZE.

wiedzieć, iż istnieją standardy języka RedCode, analo-

Ważnym elementem, sprawiającym nieco kłopotów,

gicznie jak standardy dla języków C, C++ czy Java. Ostat- jest fakt, iż w dostępie do pamięci obowiązuje adresowa-nim standardem jest ICWS'94. Dostępne są także pewne nie względne. Innymi słowy, nie ma adresu początkowego uproszczone odmiany języka RedCode. Bez względu na oraz końcowego. Adres zerowy to adres komórki, w której odmianę Red Code należy posiadać specjalny symulator aktualnie się znajdujemy, wartość 1 to adres komórki następ-56

marzec 2008

www.lpmagazine.org

57





Programowanie

Programowanie

Wojny Rdzeniowe

Wojny Rdzeniowe

nej, a wartość -1 to adres komórki poprzedniej. RedCode

dat #0, #0 oznacza umieszczenie w aktualnej

Oznacza to także, iż rdzeń jest zapętlony. Na- Przedstawiona powyżej definicja systemu MARS komórce wartości 0 w polach A oraz B, natomiast stępną komórką pamięci po ostatniej jest ko- nie jest zbyt skomplikowana, podobnie jak język dat #1, #2, oznacza umieszczenie odpowied-mórka pierwsza.

RedCode. Jednak, jak zawsze w przypadku języ- nio jedynki i dwójki. Znak $ oznacza bezpośred-Każda komórka pamięci posiada trzy ele- ka programowania podobnego do assemblera, ni adres. Przykładem zastosowania adresowania menty: pole instrukcji, pole argumentu źródło- napisanie dobrego programu nie jest łatwe.

względnego może być instrukcja kopiująca samą

wego A oraz pole argumentu docelowego B.

Pojedyncza instrukcja RedCode, podobnie siebie mov $0,$1. Ponieważ adresowanie jest Nie ma typowych rejestrów jak w rzeczywi- jak w wielu istniejących assemblerach, jest zbu- bardzo często używane, to możemy także napi-stych procesorach, jednakże dostępny jest ob- dowana z czterech elementów: etykiety, kodu in- sać mov 0, 1. Większość kompilatorów RedCo-szar pamięci nazwany P-Space, do którego, strukcji oraz dwóch pól argumentów. Schema- de dopuszcza stosowanie tego typu skrótu. Inny każdy z programów ma wyłączny dostęp. Jed- tycznie przedstawimy to, w następujący sposób: przykład instrukcji to mov #2, 1, oznaczający nak P-Space jest nowym elementem i klasycz-przeniesienie dwójki pod następny adres.

na wersja RedCode nie oferuje dostępu do do- etykieta trzyliterowy kod instrukcji

Dwa kolejne typy adresowania są repre-

datkowej przestrzeni pamięci.

[pole_A, pole_B]

zentowane przez symbole * oraz @. Pierwszy

W jednym takcie wykonywana jest tyl-

adresuje pośrednio przez pole A, drugi sym-

ko jedna instrukcja (co oznacza, że czas wy- Spis wszystkich instrukcji przedstawia tabela bol przez pole B. Oznacza to iż z pola np.: A od-konania poszczególnych typów instrukcji pt. Instrukcje RedCode. Ważną rolę pełni in- czytywany jest adres pod którym znajduje się jest taki sam), i po jej wykonaniu MARS strukcja dat, a dokładniej jej postać dat 0,0 informacja o właściwym adresie. Taki typ ad-przechodzi do wykonania instrukcji z na- (lub dat $0, $0). Jest to nielegalna instrukcja i resowania to nic innego, jak wskazanie przez stępnej komórki pamięci. Wyjątkiem jest in- jej wykonanie doprowadzi do śmierci wykony- wskaźnik, stosowane w wielu językach wyso-strukcja skoku, która przenosi sterowanie do wanego programu. Domyślnie, cały rdzeń jest kiego poziomu jak Pascal czy C. Kolejne tryby innego miejsca w pamięci. W pamięci mo- wypełniony tymi instrukcjami. Dodam jesz- adresowania są reprezentowane przez symbo-

że być wykonywanych kilkanaście progra- cze, że wyrażenia w nawiasach kwadratowych le {, } oraz <, >. Oznaczają one również adreso-mów różnych użytkowników. W takim przy- są opcjonalne np.: jeśli chcemy zapisać instruk- wanie pośrednie przy pomocy pól A oraz B. Jed-padku MARS wykonuje je kolejno, po jed- cję skoku o pięć komórek do przodu to piszemy nakże symbol { oznacza iż adres zostanie pobra-nej instrukcji.

tylko jmp 5. Argument B, nie jest potrzebny.

ny z komórki o adresie zawartym w A, ale przed

MARS dopuszcza także uruchamianie pro-

Instrukcji języka nie jest wiele, ale istnieje skokiem wartość ta zostanie zmniejszona. Pocesów potomnych w ramach programu użyt- kilka różnych sposobów adresowania. Podsta- dobnie dla symbolu }, ale tym razem zostanie kownika za pomocą instrukcji spl. Każdy z wową informacją jest fakt, iż adresowanie jest ona zwiększona. Uzupełnieniem instrukcji Red-nowo utworzonych procesów zapisywany jest względne, co zostało już wspomniane wcześniej. Code są pseudoinstrukcje sterujące procesem w kolejce zadań. System kolejno po jednej in- Jednak zastosowanie znaku # (hash) oznacza kompilacji programu. Możemy wprowadzać strukcji przetwarza procesy z listy zadań.

bezpośrednią wartość liczbową, czyli instrukcja tekstowe oznaczenia dla wartości liczbowych: nazwa EQU wartość. Instrukcja ORG etykieta

Tabela 1. Instrukcje RedCode

pozwala na ustalenie adresu początkowego dla

Instrukcja

Krótki opis

programu. Natomiast instrukcja END [etykie-

dat [A,] B

instrukcja do przechowywania danych, próba jej wykonania zabija proces

ta] oznacza koniec programu. Jeśli chcemy,

aby pewien fragment programu był powtórzo-

mov A, B

kopiowanie z A do B

ny kilka razy warto zastosować instrukcję FOR:

add A, B

dodawanie A do B, wynik zapisywany w B

sub A, B

odejmowanie A od B, wynik zapisywany w B

[zmienna] FOR n

mul A, B

mnożenie B przez A, wynik zapisywany w B

instrukcje

div A, B

dzielenie całkowite B przez A, część całkowita wyniku zapisywana w B, dziele-

ROF

nie przez zero powoduje śmierć procesu

mod A, B

dzielenie modulo B przez A, reszta z dzielenia zapisywana w B, dzielenie

Instrukcje zostaną wstawione do programu n

przez zero powoduje śmierć procesu

razy, co więcej możemy używać wyrażenia

jmp A[, B]

skok bezwarunkowy do komórki A

zmienna, które będzie zawierać aktualny nu-

mer rozwinięcia:

jmn A, B

skok do A, jeśli B jest różne od zera

jmz A, B

skok do A, jeśli B jest równe zero

xx FOR 5

djn A, B

zmniejszenie B o 1 i skok do A, jeśli B jest różne od zera

mov 0, xx

spl A[, B]

uruchomienie równoległego procesu w komórce A

ROF

stl A, B

jeśli A mniejsze od B, to omiń następną instrukcję

cmp A, B

- jeśli A jest równe B, to omiń następną instrukcję

Po kompilacji otrzymamy następujący kod:

seq A, B

sne A, B

odwrotnie niż cmp, jeśli A i B są różne, to omiń następną instrukcję

mov 0, 1

mov 0, 2

nop [A, B]

instrukcja pusta

mov 0, 3

ldp A, B

załaduj komórkę A P-Space do komórki B

mov 0, 4

stp A, B

zapisz A do komórki B P-Space

mov 0, 5

56

marzec 2008

www.lpmagazine.org

57





Programowanie

Programowanie

Wojny Rdzeniowe

Wojny Rdzeniowe

RedCode oferuje także dostęp do specjalnych Skoczek – Imp

cały rdzeń. Taki program zwykło się określać

zmiennych. Jedną z nich jest wielkość rdzenia Po opisie instrukcji RedCode, możemy napi- mianem skoczka i wbrew pozorom jest dość CORESIZE. W zmiennej WARRIORS znajduje się sać pierwszego wojownika, który posiada tyl- skuteczny. Wiele prostych programów może liczba programów uczestniczących w poje- ko jedną instrukcję mov:

zostać pokonanych przez ten program. Może-

dynku. Możemy również dokładnie opisywać,

my także kopiować co dwa pola:

na jakich operatorach działamy. Jednakże po- mov 0, 1

dane podstawowe informacje wystarczają do

mov 0, 2

przedstawienia najprostszych, ale zarazem Kopiujemy aktualną zawartość komórki rdze- mov 0, 2

najsłynniejszych wojowników RedCode.

nia do następnej. I ten sposób zamazywany jest

Przykład zastosowania instrukcji FOR jest pro-

stym rozwinięciem tej idei. Bardziej wyrafino-

wany program o sposobie działania podobnym

Kompilacja programów CoreWars oraz pMars

do skoczka to skoczek spiralny (Listing 1.)

W programie używamy naszego skocz-

Omawiane środowisko pMars i wspomniane CoreWars niestety nie są zazwyczaj dołącza-

ka (etykieta imp), który kopiuje się do ety-

ne do dystrybucji Linuxa. Oznacza to konieczność samodzielnej kompilacji oraz instalacji. kiety impsize. Będzie się on kopiował po-

Łatwiej jest dokonać kompilacji CoreWars, ponieważ pakiet ten posiada skrypt configure. dobnie jak zwykły skoczek, ale z większym Po dekompresji archiwum

przesunięciem. Co więcej dzięki instrukcji

spl powstaną cztery oddzielne procesy. To-

tar zxvpf corewars-0.9.13.tar.gz

też, jeśli nawet któryś z procesów zostanie

należy przeprowadzić konfigurację np.:

uszkodzony, pozostają jeszcze trzy inne pro-

cesy, które nadal będą sukcesywnie zamazy-

./configure --prefix=/opt

wać rdzeń. Takie rozwiązanie powoduje, iż

zwykły skoczek będzie przegrywał więk-

gdzie jak zwykle za pomocą polecenia --prefix określamy katalog docelowy. Następnie szość pojedynków.

po zakończonej konfiguracji (środowisko CoreWars wymaga obecności biblioteki GTK+ w

starszej wersji 1.2.xx), rozpoczynamy właściwą kompilację za pomocą polecenia make. Po Rozdzielacz – Split er kilku chwilach możemy zainstalować program wydając polecenie make install.

Innym prostym programem RedCode jest

Drugi z programów pMars niestety nie posiada skryptu configure, został wyposażony Splitter, którego nazwę w wolnym tłuma-tylko w skrypt makefile. Po dekompresji archiwum

czeniu najlepiej tłumaczyć jako rozdzielacz.

Pierwsza instrukcja tworzy proces potomny

tar zxvpf pmars-0.9.2-5.tar.gz

od adresu zerowego. Następnie wchodzimy

należy przejść do nowo utworzonego katalogu. Jednakże w nim nie znajdziemy pliku ma-w pętlę, pierwsza instrukcja zwiększy o dzie-

kefile. Plik ten znajduje się w podkatalogu src. Po wydaniu polecenia make rozpocznie-sięć adres instrukcji spl. Co oznacza iż na-

my proces kompilacji, a po kilku chwilach zostanie utworzony plik wykonywalny, który bę-

stępne wykonanie instrukcji spl, spowodu-

dzie gotowym symulatorem wojen rdzeniowych. Będzie to jednak tylko sam symulator, jeśli je utworzenie nowego procesu o dziesięć ko-chcemy mieć dostęp do graficznego podglądu za pomocą biblioteki SDL, należy zdefinio-mórek dalej. Jedyną instrukcją jaką umieści-

wać odpowiednią stałą -DSDLGRAPHX. Stałą tę umieszczamy w zmiennej CFLAGS. Po doko-

my pod nową pozycją jest spl. Po wykona-

naniu tej zmiany, definicja zmiennej CFLAGS przybiera następującą postać

niu przeniesienia, ponownie zwiększamy ad-

res dla instrukcji spl. Sam program przedsta-

CFLAGS = -O4 -fomit-frame-pointer $(DBG) -DSERVER -DEXT94 -DPERMUTATE -

wia się następująco:

DSDLGRAPHX $(INC)

splitter spl 0

Dodatkowo należy usunąć komentarz dla zmiennych INC oraz LIB:

loop add #10, splitter

mov splitter, @splitter

INC = `sdl-config –cflags`

jmp loop

LIB = `sdl-config –libs`

W podobny sposób możemy włączyć graficzny podgląd dla środowiska X-Window. Należy Zaletą tego programu jest tworzenie dużej ilo-do lini CFLAGS, dodać następującą definicję -DXWINGRAPHX. A następnie dodać bądź usu-

ści procesów, a ponieważ wygrywa ten program,

nąć komentarz w lini

który ciągle działa, więc Rozdzielacz ma duże

szanse na przeżycie ataku innych programów.

LIB = -L/usr/X11R6/lib -lX11

Incendiary Bomb

Koniecznie trzeba jeszcze wspomnieć o stałej -DSERVER, która jest odpowiedzialna za To kolejny prosty ale bardzo niebezpieczny obecność debuggera dla RedCode. Jej zdefiniowanie powoduje, iż pMars jest kompilo-program. Jego dwie instrukcje przedstawiają

wany w trybie serwera, co oznacza, że otrzymamy symulator pojedynków. Warto tę defini-się następująco:

cje usunąć, jeśli planujemy testować i sprawdzać, jak zachowują się programy, nad który-mi aktualnie pracujemy. Bowiem, będziemy mogli skorzystać z wbudowanego debuggera spl 0, 8

RedCode o nazwie cdb.

mov -1, <-1

58

marzec 2008

www.lpmagazine.org

59





Programowanie

Programowanie

Wojny Rdzeniowe

Wojny Rdzeniowe

Pierwsza instrukcja powołuje do życia nowy pro- Karzeł Bombiarz – Dwarf

Sam kod źródłowy, jest bardzo prosty:

ces od adresu zerowego. Jednakże drugi argu- Zasada działania tego programu jest rów-ment spl to adres, gdzie instrukcja mov ma prze- nież bardzo prosta. Co cztery komórki bomb DAT #0

nieść instrukcję spl. Wartość adresu jak widać umieszczamy bombę, czyli instrukcję dat dwarf ADD #4, bomb jest zmniejsza o jedność, więc już po chwili po- 0,0 która jak wiadomo prowadzi do zabi- MOV bomb, @bomb wstanie osiem instrukcji spl, które nieustanie bę- cia aktywnego procesu. Ponieważ nasz pro- JMP dwarf dą tworzyć nowe procesy. Możemy nawet zwięk- gram liczy trzy linie, a bombę umieszczamy szyć wartość pola B instrukcji na inną, a zobacz- co cztery komórki, oznacza to, iż ominie- Replicators – Replikator Mysz my, że spowoduje to zmianę ilości instrukcji spl. my własny kod. Inne programy mogą zostać Ostatnim przykładem programu jaki zostanie po-Ostatecznie instrukcja mov zostanie zamazana unieszkodliwione przez naszego wojownika kazany jest program o nazwie Mice, czyli Mysz.

przez instrukcję spl i powstanie swoista pętla in- bardzo szybko, jeśli uda się nam trafić choć- Program ten został napisany w roku 1986 przez strukcji powołujących do życia do nowe procesy. by jedną bombą.

Chipa Wendel a. Jego zadaniem jest kopiowa-

nie się po rdzeniu w pewnych odstępach określo-

nych przez wartość określoną pod etykietą spa-

cer. Powoływane są także nowe procesy instruk-

cją spl. Kopiowanie kodu następuje przy uży-

ciu instrukcji mov oraz instrukcji pętli djz. Pro-

gram Mysz tworzy nowe procesy, które kopiują

kod do następnego adresu. W ten sposób trudniej

jest usunąć program z pamięci, ponieważ po usu-

nięciu pierwszego procesu, pozostaje drugi, który

dysponuje pełnym kodem programu. Nowe po-

wstałe procesy także przenoszą kod w inne miej-

sca pamięci. Tego typu programy nazywa się re-

plikatorami, ponieważ przenoszą się samodziel-

nie po pamięci, a każdy proces jest niezależny.

Program ten działa niewątpliwe w sposób podob-

ny do typowego wirusa komputerowego, który

infekuje kolejne programy. Pełen kod źródłowe-

go programu jest następujący (Listing 2.)

Jak uruchamiać programy?

Po podaniu kilku przykładów, należy się jeszcze

słowo dla tych użytkowników, którzy chcieliby

uruchomić zamieszczone programy. W pierw-

Rysunek 1. Program Corewars i pojedynek miedzy czterema wojownikami

Listing 1. Kod źródłowy dla skoczka spiralnego

impsize equ 2667

example spl 4

spl 2

jmp imp+(0*impsize)

jmp imp+(1*impsize)

spl 2

jmp imp+(2*impsize)

jmp imp+(3*impsize)

imp mov 0, impsize

Listing 2. Replikator Mysz

top dat #0, #0

start mov #12, top

loop mov @Top,
djn loop, top

spl @target,0

spacer equ 653

add #spacer, target

jmz start, top

target dat #0, #833

end Start

Rysunek 2. Program pMars oraz walka między skoczkami

58

marzec 2008

www.lpmagazine.org

59





Programowanie

Wojny Rdzeniowe

szej kolejności należy utworzyć pliki źródłowe uruchomić program pmars podając jako argu- ilość rund np.: na dziesięć, to należy zastoso-z programami. Do tego celu wystarczy dowolny ment nazwę pliku źródłowego programu:

wać parametr -r:

edytor tekstowy np.: GEdit w GNOME czy Ka-

te w KDE, albo typowe narzędzie konsolowe jak pmars imp.red

pmars -r 10 imp.red dwarf.red

choćby VIM. Wszystkie programy opisane w ar-

tykule znajdują się także na płycie DVD.

Gdy chcemy zobaczyć pojedynek programów, Jeśli, chcemy dokładnie śledzić wykonywa-Uruchomienie programów, z poziomu apli- to podajemy kilka nazw programów z kodem nie się programu, to warto skorzystać z wbu-kacji pMars nie jest zbyt trudne. Jednakże mu- źródłowym np.:

dowanego debuggera o nazwie cdb w progra-

simy korzystać z konsoli. Warto w katalogu do-

mie pMars. Chcąc śledzić pracę np.: programu

mowym utworzyć nowy podkatalog i dokonać pmars imp.red dwarf.red

Dwarf uruchamiamy symulator MARS'a, w na-

kompilacji programu pMars, lub przenieść z

stępujący sposób:

płyt DVD gotową wersję pMarsa (dla bibliote- Naturalnie program pmars przyjmuje kilka-ki SDL albo X-Windows).

naście parametrów. Pierwszym bardzo istot- pmars -e dwarf.red

Jeśli chcemy sprawdzić jak wykonuje się nym jest parametr -r. Domyślnie mamy tyl-

program jednego z wojowników, wystarczy ko jedną rundę, więc jeśli chcemy zmienić Poleceń debuggera jest dość sporo, krótki opis wszystkich zobaczymy po wydaniu polecenia

help lub po prostu po naciśnięciu klawisza en-

ter. Instrukcja step (możemy także korzystać

W Sieci

ze skróconej wersji – jedna litera s) wykonuje

program instrukcja po instrukcji. Możemy doko-

ó Oryginalne artykuły o Core Wars

nać deasemblacji wybranego zakresu, np.: pole-



http://www.koth.org/info/sciam/

cenie list 1,5 wyświetli zawartość rdzenia od

ó śKról Wzgórza”, (ang. King of the Hil – KOTH), strona zawiera podstawowe informa-komórki numer jeden do komórki numer pięć.

cje oraz adresy o CoreWars

Śledzenie instrukcja po instrukcji jest



http://www.koth.org/

żmudne, więc warto użyć polecenia trace,

ó Strona programu pMars, oficjalnego systemu do symulacji wojen rdzeniowych

które po każdym wydanym poleceniu go, bądź



http://www.koth.org/pmars/

po wciśniętym klawiszu enter, będzie wyko-

ó Interesująca strona o CoreWars, zawiera kod programów oraz odnośniki do kilku cie-nywać cały zestaw poleceń, aż ponownie ste-

kawych publikacji o CoreWars

rowanie wróci do punktu w którym wykonane



http://corewar.atspace.com/

zostało polecenie trace. Gdy śledzimy pojedy-

ó Polska strona o CoreWars, warto przeczytać

nek, polecenie progress pokaże aktualny przy-



http://www.knf.pw.edu.pl/~adamow/corewar

dział punktów dla każdego programu.

ó Nieco starsze środowisko do wojen rdzeniowych, lecz równie dobre jak pMars



http://sourceforge.net/projects/corewars/

Podsumowanie

ó Strona serwera do potyczek związana z programem Corewars

Wielu osobom może się wydawać, że wpatry-



http://sal.math.ualberta.ca/

wanie się w migoczące kwadraty, to zwykła

strata czasu. Nie jest to sprawiedliwa opinia,

gdyż warto choćby wypróbować przedstawio-

ne programy, choć są to tylko najprostsze przy-

kłady. Koniecznie trzeba to zrobić, jeśli chcemy

pisać bardziej skomplikowane programy. W In-

ternecie można odszukać wiele interesujących

przykładów stanowiących prawdziwe wyzwa-

nie. Jednakże piękno wojen rdzeniowych ujaw-

nia się w małych programach, opartych o pew-

ną strategię bądź ideę. Wszystkie wykorzy-

stane biblioteki, kod źródłowy programu oraz

wszystkie listingi z artykułu znajdują się na

stronie http://www.lpmagazine.org.

O autorze

Autor zajmuje się tworzeniem oprogramo-

wania dla WIN32 i Linuksa. Zainteresowa-

nia: teoria języków programowania oraz

dobra literatura.

Rysunek 3. Program pMars i debugger cdb podczas śledzenia programu Dwarf

Kontakt z autorem: autorzy@linux.com.pl.

60

marzec 2008







Wyszukiwarka

Podobne podstrony:
2008 03 Scalix migracja z MS Nieznany
2008 03 Sunshine id 2061320 Nieznany
2008 03 Puppy Linux a Little Li Nieznany
Wojny w Imie Boga Nieznany
1 03 Zyzny polksiezyc w starozy Nieznany
wojny rzeczpospolitej z siasiad Nieznany
03 elementy jezykow programowania
Choroba Cushinga u koni (2008 03) Gołyński
2008 03 Making Music Connecting a Midi Keyboard to Your Linux System
2008 Frodl Reduced gray matter Nieznany
2008 03 15 alrauna hibernate
2008 03 Safer Box Backing Up for Portables with Box Backup

więcej podobnych podstron