AMIGA REVIEW online
  Uvodná stránka     Software     Hry     Obaly     Download     Amiga na PC     Amiga Forever  

ASSEMBLER A SYSTÉM


Ahoj, tady je Joe of Agony. Jsem zde, protože minulí člověkově, kteří měli psát tuhle rubriku, ji psát přestali. To způsobilo menší změnu, doufám že k lepšímu... a teď jste v moci šíleného programátora, který za truchlivých nocí v bledé záři monitorů... No nic. Každopádně o nic nepřijdete! Pokusím se navázat na úvod, který po sobě zanechal můj předchůdce, a splnit co vám nasliboval... (plán splníme, ba překročíme!) Howgh!

V minulé části tohoto seriálu jste (snad) získali jakouž takouž představu o dvojkové a šestnáctkové soustavě a o tom, k čemu jsou dobré a bylo vám předhozeno něco informací o procesoru, registrech, paměti atd. Pro jistotu udělám malé shrnutí, na které navážu snůškou dat ohledně programování v assembleru...

Procesor, a to stále ještě obecně
Jak už jistě víte, procesor řady MC68000 se z pohledu systémového programátora (programátora, který ihned nezlikviduje systém jen proto, že s ním neumí spolupracovat) jeví jako skupina registrů. Jsou to:
- Adresové registry A0-A7,
- Datové registry D0-D7,
- Stavový registr SR
Procesor obsahuje i jiné registry, ty však jsou většinou přístupné jen ze Supervisor-módu nebo jejich změna může vážně narušit funkci celého systému, takže je raději necháme na pokoji. K jejich ovládání nabízí systém speciální služby.

Datové registry
Datové registry D0-D7 jsou 32-bitové, ale s každým z nich lze pracovat jako by byl 8, 16 nebo 32 bitový. To znamená, že v nich lze uchovávat a zpracovávat BYTE, WORD i LONG. Tyto registry jsou vlastně jakousi "pracovní oblastí", ve které se provádí naprostá většina výpočtů a operací prováděných programem. Výhodou práce s registry je jejich RYCHLOST. Je to proto, že tyto registry má procesor "po ruce", kdežto přístup do paměti je mnohem pomalejší. Je proto krajně výhodné na začátku zpracování data načíst do datových registrů procesoru, tam s nimi provést požadovanou operaci, a potom výsledek uložit zpět do paměti.

Stavový registr SR
Stavový registr je z pohledu USER-mode velký pouze 5 bitů. Těchto 5 bitů jsou tak zvané "příznaky" nebo "flagy". Jsou to jednotlivé bity, které jsou nastavovány po provedení některých operací procesoru podle výsledků těchto operací. Tyto příznaky je pak možno testovat a na jejich základě provést nebo neprovést nějakou operaci (např. skok na jiné místo programu). Tyto flagy jsou:
X, N, Z, V, C.
Každý flag je nastavován za jiných podmínek a znamená něco jiného.
- "Z" (zero) je příznak který je nastavován v případě, když výsledek předchozí operace byl roven nule. Bude to asi váš nejvíce používaný příznak:.
- "N" (negative) je nastaven, pokud nejvyšší bit výsledku předchozí operace je roven 1. Pokud se tedy na onen výsledek díváme jako na číslo se znaménkem, "N" je nastaven, byl-li tento výsledek záporný (tj. menší než 0).
- "C" (carry) je nastaven, pokud došlo při minulé operaci k "přetečení" výsledku. To se například může stát, když k BAJTU, (ed. BAJT je BYTE - OK? Vše jasné? Nebudu to přeci všude opravovat...) který má hodnotu 255 ($FF) přičtete 1. 255+1 = 256, ($FF+$01=$100). Hodnota 256 je už příliš velká, aby se vešla do 8 bitů BAJTU, a proto bude nejvyšší bit výsledku ztracen. Nejlépe je to vidět na šestnáctkovém zápisu této operace: $FF+$01=$100, ale v bajte zůstanou jen dvě poslední číslice výsledku. Devátý bit (který je navíc) je přenesen do příznaku "C". U odečítání je tomu podobně - když dojde k přetečení, příznak je nastaven. Tento případ se vztahuje k HODNOTÁM BEZ ZNAMÉNKA. Příznak "C" se nastavuje i jinými operacemi, více o tom při popisu těchto operací.
- "V" (overflow) se používá v případě, když výsledek je hodnota SE ZNAMÉNKEM. Jeho funkce je obdobná jako u příznaku "C", ten však byl pro hodnoty bez znaménka. Protože procesor neví, jestli na výsledek hledíme jako na číslo se znaménkem nebo bez znaménka (a v podstatě je mu to jedno), nastavují se podle operace jak "C" tak i "V" a je na nás, který z nich nás zajímá (protože my víme, je-li to hodnota se znaménkem nebo bez). Rozdíl je v tom, že přenos "carry" nastává jindy než přenos "overflow". Nejlépe to ozřejmí příklad: Mějme BYTE SE ZNAMÉNKEM (A) a BYTE BEZ ZNAMÉNKA (B). Jak víte, rozsah (A) je od -128 do +127, rozsah (B) od 0 do 255. Jak (A) tak i (B) budou mít hodnotu 126 ($7E). Co se stane, když k (A) i (B) přičteme 3? V případě (A) dostaneme 126($7E)+3=129($81),což je mimo rozsah. Bude tedy nastaven příznak přenosu (overflow) a výsledná hodnota (A) bude po operaci -127($81). V případě (B) dostaneme 126($7E)+3 = 129($81), což je v platném rozsahu, takže příznak přenosu (carry) nastaven nebude. Všimněte si, že v obou případech je šestnáctková reprezentace čísel stejná, rozdíl je pouze ve způsobu, jakým tyto hodnoty interpretujeme.
- "X" je v podstatě místo na přebývající bit při přetečení při sčítání a odčítání a jiných operacích. Tento bit je ovlivňován mnohem menším okruhem operací než "C" nebo "V", což je výhodné, protože hodnota tohoto příznaku nemusí být nikam ukládána než se použije. Více při popisu operací ovlivňujících tento příznak.
Popisy významů které jsem uvedl jsou samozřejmě jen ty nejpoužívanější - existují výjimky... více o tom v popisu jednotlivých operací .

Adresové registry
Adresové registry A0-A7 jsou všechny 32 bitové. Používají se (jak už sám jejich název napovídá) k ukládání ADRES. Adresa, jak bylo už řečeno minule, jednoznačně identifikuje místo v paměti, se kterým chceme pracovat. Více o tom v části zabývající se adresovacími módy. Registr A7 (nazývaný také SP nebo USP) se používá jako ukazatel zásobníku. Tento zásobník se používá na ukládání návratových adres při skocích do podprogramů, na ukládání obsahu registrů procesoru když víme, že je budeme za chvilku ještě potřebovat, případně se na zásobníku vyhrazuje místo na dočasné proměnné, například v rámci jednoho podprogramu. Zvláštností adresových registrů je, že při operacích s nimi většinou NEJSOU podle výsledků nastavovány příznaky v registru SR. To většinou ušetří ukládání příznaků v případě, kdy třeba po testovací operaci (která nastaví příznaky) potřebujeme ještě načíst nějakou adresu do adresového registru. Na rozdíl od datových registrů nelze s adresovými registry pracovat jako s BAJTY nebo WORDY. Nic nám však nebrání v jejich využití třeba k dočasnému uložení obsahu některého datového registru, když se nám datových registrů nedostává.

Co s registry?
Procesor umožňuje všechny registry (tím myslím datové a adresové) navzájem vyměňovat a kopírovat data z jednoho do druhého. S datovými registry lze provádět spoustu různých operací, jak si později ukážeme. S adresovými registry lze provádět o něco méně operací, je to však dáno jejich určením.

Paměť, taktéž obecně
Co se týče paměti, jejím účelem je uchovávat informace pro procesor, případně pro jiné čipy, které do ní mají přístup. Ze strany procesoru se paměť jeví jako hromada očíslovaných políček, ze kterých může procesor číst data nebo do nich data zapisovat. Každé toto políčko je velké 1 BYTE. Každý byte má svoji ADRESU. Je to číslo, kterým se procesor odkazuje na tento určitý byte paměti. U MC68000 může toto číslo být velké 24 bitů, u vyšších procesorů je to 32 bitů. Celý rozsah všech možných adres se nazývá ADRESNÍM PROSTOREM PROCESORU. U MC68000 je to 16 megabajtů, u vyšších procesorů dokonce 4 gigabajty. Je to tedy víc než dostatečný rozsah, který, jak zcela jistě tušíte, není zcela využit. Celý adresní prostor je u Amigy rozdělen na jakési "oblasti". V některých těchto oblastech buď není VŮBEC NIC, nebo tam může být paměť, případně speciální registry ostatních čipů Amigy, prostřednictvím kterých je procesor ovládá. Tyto registry se procesoru v podstatě jeví jako normální paměť. Některé tyto registry se dají jenom číst, do jiných lze jen zapisovat a ještě jiné lze číst i zapisovat. Rozdíl mezi těmito řídícími registry a obyčejnou pamětí je v tom, že v paměti se jen ukládá to, co tam procesor naposledy zapsal, kdežto když procesor něco zapíše do řídícího registru některého čipu, tento čip se to okamžitě dozví, přečte si to a podle toho provede nějakou operaci. Například když zapíšete nějaký bajt do registru obvodu CIA, který má na starosti paralelní port. Data která tam procesor zapsal se ihned objeví v podobě elektronických signálů na konektoru paralelního portu a navíc se ještě generuje impuls, který uvědomí dejme tomu tiskárnu, která je na paralelním portu připojena, že si má převzít nová data. O ovládání hardware prostřednictvím těchto registrů si povíme ve zvláštní kapitole.
Ještě k paměti. Existují v podstatě dva základní druhy paměti - RAM a ROM. Paměť RAM slouží k uchovávání informací po dobu, kdy je počítač zapnutý. Po vypnutí napájení je její obsah nenávratně ztracen. Procesor do ní může data zapisovat i z ní data číst. Oproti tomu paměť ROM byla při její výrobě napevno naplněna daty, která tam zůstávají i po odpojení napájecího napětí. Paměť ROM je možno pouze číst. Musím vás ještě upozornit na organizaci paměti. Jak už víte, procesor umí pracovat s daty (čísly) širokými 8 (BYTE), 16 (WORD) nebo 32 (LONG) bitů. Je třeba si uvědomit, že paměť jako taková se skládá z BAJTŮ jenom LOGICKY. Ve skutečnosti procesor MC68000 vzhledem ke své 16-bitové vnější architektuře může k paměti přistupovat jen po CELÝCH WORDECH. Vypadá to asi takhle:
- 16 bitů = 2 bajty -
( adresa 0 ) ( adresa 1)
( adresa 2 ) ( adresa 3 )
( adresa 4 ) ( adresa 5 )
.. atd ...
Vnitřek závorky představuje 1 BAJT. Procesor načítá z paměti vždycky celý WORD ze SUDÉ ADRESY. Pokud načítáme BAJTY, nic se neděje. Když třeba chce procesor načíst bajt z adresy 3, přečte prostě celý WORD z adresy 2, který v sobě obsahuje bajt z adresy 2 i bajt z adresy 3. Na bajt z adresy 2 se procesor prostě vykašle a nechá si jenom bajt z adresy 3. Horší situace nastane, čteme-li WORD nebo LONG. Pokud čteme WORD ze SUDÉ ADRESY (např. z adresy 4), všechno je OK, procesor ho načte celý najednou. Katastrofa ovšem nastává, pokud se pokusíme načíst WORD z LICHÉ ADRESY (třeba 3). Jak víte, word jsou v podstatě 2 bajty. JENŽE: První bajt kýženého wordu je součástí wordu paměti na adrese 2, kdežto druhý byte našeho wordu je umístěn ve wordu paměti na adrese 4!!! S tímto faktem se MC68000 neumí vypořádat, a přejde tudíž do chybového stavu, jehož výsledkem je zhroucení vašeho programu. LONG načítá MC68000 jako dva WORDY za sebou, tudíž je tu stejný problém. Co s tím? Na to je jednoduchá odpověd` prostě nebudeme dávat žádné WORDY ani LONGY na liché adresy Tomuto opatření se říká ALIGNMENT, čili česky řekněme ZAROVNÁVÁNÍ. V assembleru existují prostředky, které nám alignment umožňují. Chtěl bych ještě upozornit, že samotné INSTRUKCE PROCESORU se skládají z WORDŮ. Na to pozor, ani samotný program nesmí být na liché adrese!!! U procesorů MC68020 a lepších byl tento problém odstraněn tím, že se čtení prostě provede dvakrát a načtená data se složí dohromady. Vzhledem k tomu, že přístup do paměti je ta nejpomalejší věc, co může procesor dělat, je pořád výhodné zarovnávat data na násobky 2. NAVÍC: MC68020+ procesory mají 32-bitovou vnější architekturu, takže jejich přístup do paměti probíhá dokonce po celých LONGách (lonzích? longs? Sakra, pokud jde o odborné výrazy, čeština nám moc nepomůže... Takže: Pokud to ještě neumíte, začněte se UČIT ANGLICKY!!! To myslím zcela vážně, protože ďábelský programátor se bez dobré znalosti angličtiny prostě neobejde! Angličtina je tradičně jediným univerzálním počítačovým jazykem. Programátory, co udělají geniální program, ale jenom ve svahilštině, u nás v Kansas City věšíme!!!). Takže zpět k tématu. Větší šířka datové sběrnice (32 bitů) přispívá samozřejmě k vyšší rychlosti, protože třeba celý LONG je možné načíst najednou. Ale zase - JEN Z ADRESY, KTERÁ JE NÁSOBKEM 4! Vypadá to zase nějak takhle:
32 bitů = 4 bajty
(adresa 0) (adresa 1) (adresa 2) (adresa 3)
(adresa 4) (adresa 5) (adresa 6) (adresa 7)
(adresa 8) ..... atd .........
Obecně, tedy z pohledu programátora který chce aby jeho geniální programy fungovaly maximálně, budeme tedy pokud možno všechny LONGY zarovnávat na adresy o násobcích 4, a všechny WORDY na adresy o násobcích 2 (tedy sudé). To pokud jde o data. Co se týče začátku programu, doporučuji zarovnávat ho na násobky 4, aby se zbytečně nečetl word těsně před programem...

Program v assembleru a assembler
Aby se mi lépe vysvětlovala adresace, naučíme se něco o tom, jak vlastně vypadá program v assembleru, abychom si mohli zkoušet malé příkládky. Program v assembleru je v podstatě textový soubor, obsahující popis operací procesoru v textové formě, který je dobře čitelný pro člověka. Pro procesor však není čitelná ani trochu, je potřeba tento textový soubor PŘELOŽIT do strojového kódu, kterému procesor rozumí (ale zase člověk ani trochu). K tomuto překladu slouží program nazývaný ASSEMBLER. Tady je vidět, jak se směšují různé pojmy - assembler znamená jak PROGRAM, kterým přeložíme zdrojový textový soubor do spustitelného binárního souboru (tzv. executable, čili v hantýrce "exáče"), tak i samotný symbolický jazyk, ve kterém je tento textový soubor napsán. Tento executable soubor je pak při jeho spuštění načten do paměti RAM a spuštěn. Samotný běh programu vypadá tak, že procesor postupně od začátku programu vybírá z paměti instrukce tak jak jdou za sebou a ihned je vykonává. Existují různé typy instrukcí - přesuny dat, matematické a logické operace, různé skoky, v programu. Umění programátorovo spočívá tedy v umění rozložit nějaký složitý program na tyto jednotlivé kroky, aby procesor při jejich vykonávání dělal přesně to, co po něm chceme. Pokud chcete vidět nějaký executable soubor, stačí se kouknout do adresáře "C" vašeho Workbenche. Spouštění vašich programů je na Amize možné v podstatě dvěma způsoby - z CLI napsáním jména vašeho programu a z Workbenche dvojím nakliknutím ikony vašeho programu. Než si povíme něco víc o multitaskingu a systému, budeme používat pouze první způsob - CLI (tedy spíš Shell, ne? Nemyslím že by byl dobrý nápad matlat se s programováním pod OS 1.3! Kdo máte starou A500 a myslíte to s programováním vážně, doporučuji prodat A500 nějakému balíkovi na hraní a zakoupit fungl novou A1200, pokud možno s harddiskem alespoň 60 MB, jako mám já. Tedy - úplně nejraději si ji nechte přivézt z Německa, protože některé firmy u nás prodávají bez uzardění počítače nakoupené jakožto VADNÉ jako NOVÉ!!! Jeden můj kamarád byl vracet novou A1200 ČTYŘIKRÁT, pokaždé mu ji vyměnili, pokaždé mu dali jinak vadnou, a počtvrté dostal tu co mu dali poprvé... (prostě Zkopaná Amiga) byl z toho tak zblblej, že si tu čtvrtou NECHAL i přes vadný floppy drive a bootuje přes externí mechaniku - TAKŽE POZOR!!! Zpět k assemblerům. Existují v podstatě dva typy assemblerů: První jsou programy spouštěné z Shellu podobně jako příkazy AmigaDOSu, které jako parametr dostanou jméno textového souboru a vygenerují z něj executable. Druhým typem jsou assemblery s vestavěným textovým editorem, jako je například AsmOne/TRASHM One, doporučovaný vám mým předchůdcem. Já osobně tento program považuji za značně NEVHODNÝ pro naše účely, a to ze dvou důvodů:
1) Je STARÝ a umí jen instrukce MC68000 neumí novější procesory (viděl jsem sice verzi která je umět měla, ale byla natolik nestabilní, že k jejímu zhroucení stačil pouhý stisk klávesy RETURN v editoru - fuj!
2) AsmOne má sice hezké prostředíčko, jenže neexistuje v něm způsob, jak LEGÁLNĚ SPUSTIT PROGRAM - tj. jakoby z CLI nebo z Workbenche. Pokud program lze spustit v ASMONE, nelze ho spustit z Workbenche a obráceně - nakonec vám nezbude než program dost nepohodlně uložit na disk a spustit ho z CLI. Tahle vlastnost degraduje AsmOne/TRASHM One na prostředek na psaní a zkoušení krátkých rutinek pro MC68000. Ze začátku by se nám mohl docela hodit, ale není to nic na psaní větších systémových programů (ed. většina skvělých dem je však napsaná v Trashovi).
Já osobně preferuji assemblery prvního druhu, protože v kombinaci s vhodným textovým editorem se vyrovnají druhému druhu, toto spojení je však lehce upravitelné a univerzálnější. Navíc se s ním lépe vytváří větší programy (s pomocí linkeru a knihoven...) Asi nejlepší assembler, co jsem zatím viděl, je podle mne DEVPAC verze 3.04, protože obsahuje jak integrované prostředí, ve kterém je možné pracovat jako v AsmOne, ale bez výše uvedených nedostatků, tak i assembler který je možné používat z CLI. Navíc balík obsahuje i debugger. Devpac je však komerční produkt a u nás ho těžko seženeme, takže se budeme muset poohlédnout v oblasti shareware. Odtud bych doporučil PhxAss V4.00, který by snad mohl být k dispozici na PD discích od Atlantidy. Našel jsem ho na Aminetu v síti Internet. Protože se různé assemblery v detailech liší, pokusím se všechny příklady koncipovat tak, aby fungovaly pokud možno všude.

Způsob zápisu programu v Assembleru
Jak jsem se už zmínil, program v assembleru je textový soubor. Tento textový soubor je organizován po řádcích. Na každém řádku programu může být maximálně jedna instrukce nebo pseudoinstrukce. Instrukce je textové vyjádření nějaké operace procesoru, která má být na tomto místě programu. Pseudoinstrukce je také instrukce, ale ne pro procesor, ale pro ASSEMBLER který tento program překládá. Právě v pseudoinstrukcích bývají největší rozdíly mezi různými assemblery, protože narozdíl od instrukcí procesoru pseudoinstrukce nebyly nijak standardizovány. Jeden řádek programu v assembleru by mohl vypadat například takto:
Start MOVE.L #123456,D0 ;d0=123456
Na tomto řádku vidíme několik věcí:
- "Start" na začátku řádku je takzvaný LABEL [lejbl] (česky návěstí). Je to jakási značka, odkazující na určité místo v programu. Pokud bychom chtěli provést v programu skok právě na tento řádek, odkázali bychom se na něj právě pomocí návěstí "Start".
- "MOVE.L" je takzvaný OPCODE ("MOVE") následovaný příponou ".L". Opcode je jakýmsi kódem označujícím požadovanou operaci procesoru. V tomto případě je to "move", což je kód pro přesun (kopírování) dat ze zdrojového operandu do cílového operandu. Přípona za tečkou udává, jaký typ nebo velikost mají kopírovaná data - zdali je to BYTE, WORD nebo LONG. Zcela neočekávaně první písmena názvů souhlasí s příponami. Teď už tedy víme, že tato instrukce bude přesouvat jeden LONG odněkud někam.
- "#123456,D0" jsou parametry čili operandy pro daný opcode. V podstatě určují, s čím bude daná operace prováděna. V našem případě je to zdrojový operand "#123456" a cílový operand "D0", oddělené čárkou. Zdrojový operand je vždy uveden VLEVO, cílový VPRAVO (podle vzoru CO,KAM). "#123456" tady znamená KONSTANTU 123456. "D0" je označení REGISTRU D0. Protože u opcode byla přípona ".L", bude výsledkem celé instrukce zkopírování konstanty 123456 (32 bitů-LONG) do registru D0, čili nastavení D0 na hodnotu 123456. Jasný?
- ";d0=123456" je komentář, stručně vysvětlující instrukci. Komentáře jsou vždy za instrukcí a začínají středníkem. Komentářem je vše co je na řádku za středníkem až do konce řádku. Existuje ještě jeden druh komentáře, a to řádek začínající hvězdičkou. Tady si ale nejsem jist jestli to funguje pro všechny assemblery.
Když to tedy shrnu, je řádek v podstatě rozdělen na několik polí:
<návěstí> <opcode> <operandy> <komentář>
Návěstí musí začínat vždy bezprostředně na začátku řádku. Samozřejmě návěstí je jen na těch řádcích, na které se chceme odněkud odkazovat. Samozřejmě nemohou být dvě návěstí na jednom řádku. Pokud bychom z nějakého důvodu chtěli mít na nějakém místě programu dvě návěstí, uděláme to takto:
<návěstí1> <návěstí2> <zbytek řádky....>
Na řádku nemusí být opcode, potom jsme pořád jakoby na stejném místě programu. Operandy se různí podle opcode (žádný, jeden, dva...)

Prográmek na závěr
Abyste měli nějakou představu, jak program v assembleru vypadá, a abyste viděli už konečně něco, co "něco dělá", tak tady je malinký prográmek, který existuje snad ve všech programovacích jazycích. Opište ho do textového souboru jménem "Hello.asm" a přeložte... pro PhxAss by překlad vypadal asi takto:
1> PhxAss Hello.asm
PhxAss MC680x0/68851/6888x Macro Assembler V4.00 Written by F.Wille (Herford, GERMANY) in 1991-94 Pass 1 Pass 2 00 No error.
44 lines in 0.07 sec = 37714 lines/min.
Global symbols: 12
Local symbols: 2
Bytes gained by optimization: 4
Code: 1 section(s) 87 bytes
Data: none
BSS: none
1> hello
Nazdar mamlasos!
1>

 

;=========================
;Hello.asm - malý testík
;=========================
;exec.library:
_LVOOpenLibrary = -552
_LVOCloseLibrary = -414
;dos.library:
_LVOOutput = -60
_LVOWrite = -48

section prg,code
START move.l 4.w,a6 ; báze exec do a6
lea dosname(pc),a1 ; jméno dos.library
moveq #0,d0 ; jakákoli verze
jsr _LVOOpenLibrary(a6) ; otevřít
tst.l d0 ; mám dos.library?
beq .fuj1 ; ne->padám
move.l d0,a6 ; jo->do a6 s ní
jsr LVOOutput(a6) ; zjistit výstup
move.l d0,d1 ; mám ho v D1?
beq .fuj2 ; ne->padám
move.l #text,d2 ; adresu textu do d2
move.l #textlen,d3 ; délku textu do d3
jsr _LVOWrite(a6) ; Vypsat
.fuj2 move.l a6,a1 ; dosbase do a1
move.l 4.w,a6 ; execbase do a6
jsr LVOCloseLibrary(a6) ; zavřít dos
.fuj1 moveq #0,d0 ; normální kód
rts ; skončit

dosname dc.b "dos.library",0 ; jméno dosu
text dc.b "Nazdar mamlasos!",10 ; text,<LF>
textlen equ *-text ; výpočet délky textu

Vytlačiť článok


© ATLANTIDA Publishing Všechna práva vyhrazena.
Žádna část nesmí být reprodukována nebo jinak šířena bez písemného svolení vydavatele.



Amiga na Vašem PC rychle, snadno a zdarma!


none

AMIGA REVIEW

57 ( 11-12 / 2000 )
56 ( 9-10 / 2000 )
55 ( 7-8 / 2000 )
54 ( 5-6 / 2000 )
53 ( 3-4 / 2000 )
52 ( 1-2 / 2000 )
 
51 ( 12 / 1999 )
50 ( 11 / 1999 )
49 ( 10 / 1999 )
48 ( 9 / 1999 )
46-47 ( 7-8 / 1999 )
45 ( 6 / 1999 )
44 ( 5 / 1999 )
43 ( 4 / 1999 )
42 ( 3 / 1999 )
41 ( 2 / 1999 )
40 ( 1 / 1999 )
 
39 ( 12 / 1998 )
38 ( 11 / 1998 )
37 ( 10 / 1998 )
36 ( 9 / 1998 )
35 ( x / 1998 )
34 ( x / 1998 )
33 ( 1-2 / 1998 )
 
32 ( 11-12 / 1997 )
31 ( 9-10 / 1997 )
30 ( 7-8 / 1997 )
29 ( 6 / 1997 )
28 ( 5 / 1997 )
27 ( 4 / 1997 )
26 ( 3 / 1997 )
25 ( 2 / 1997 )
24 ( 1 / 1997 )
 
23 ( 12 / 1996 )
22 ( 11 / 1996 )
21 ( 10 / 1996 )
20 ( 9 / 1996 )
18-19 ( 7-8 / 1996 )
17 ( 6 / 1996 )
16 ( 5 / 1996 )
15 ( 4 / 1996 )
14 ( 3 / 1996 )
13 ( 2 / 1996 )
12 ( 1 / 1996 )
 
11 ( 12 / 1995 )
10 ( 11 / 1995 )
9 ( 10 / 1995 )
8 ( 9 / 1995 )
7 ( 7 / 1995 )
6 ( 5 / 1995 )

ATLANTIDA NEWS

5 ( 3 / 1995 )
4 ( 1 / 1995 )
 
3 ( 11 / 1994 )
2 ( 9 / 1994 )
1 ( 7 / 1994 )
0 ( 5 / 1994 )