· ąF.Rendszerł ° » ľPart I.Ľ ˝ Előszó: Ez a cikk a PoWeR #8-ban `Programozás - az alapok` címen szereplő iromány folytatása.Ľ Aki a PoWeR #8-ban szereplő programot begépelte, meglepődve tapasztalhatta, hogy sajnos nem fordította le az ASSEMBLER (Már aki egyáltalán ASSEMBLER-ben próbálta...). Szóval ez azért van, mert egy pár, általunk használt szimbólumot nem ismert fel. Például az _LVOOldOpenLibrary nevű offszetet. Ezek az offszetek, meg még egy csomó más adat, struktúra stb. ún. ľinclude-file-okbaĽ van gyűjtve. Programírás előtt eldöntöd, hogy mely LIBRARY-ket akarod használni, majd a hozzájuk tartozó include-file-okat beinclude-ozod. Ez az ASSEMBLER >include< utasításával történik. Az előbbi program futtatásához például az exec.library offszetjeire van szükség. Persze ha csak két rendszerrutint használunk, akkor még nem érdemes az exec-hez tartozó összes include-ot betölteni, elég csak ez a két offszet. Ja, azt nem írtam még le, hogy mi is az az offszet. Naszóval, amikor megnyitjuk a LIBRARY-t, visszakapunk a D0-ban egy címet. Ezen a címen egy csomó érdekes dolog van, de főleg az ELőTTE lévő dolgok érdekelnek minket. ˝ Itt van ugyanis az adott LIBRARY ugrótáblája.Ľ Ez azt jelenti, hogy egy csomó JMP utasítás van itt. Az include-file-okban levő offszetek ezeknek a JMP-knek a relatív címeit tartalmazzák, a D0-ban visszakapott értékhez képest. Mivel a visszakapott cím ELőTT van az ugrótábla, ezért az offszetek mindig negatívok. Tehát egy LIBRARY valamelyik rutinját a következőképpen lehet meghívni: ľ ... ... jsr _LVONameOfRutin(a6) tst.l d0 beq.s _Valami_Hiba_Van ... ...Ľ ˝Természetesen a LIBRARY báziscímének az A6-ban kell lennie.Ľ Bármely LIBRARY meghívása után a D0-ban a kimeneti érték. Ha ez 0, akkor valami hiba folytán nem sikerült a végrehajtás. Fontos tudni, hogy a rendszerrutinok nem hagyják változatlanul a regisztereket. Főleg az első három-négy regisztert szokták használni, szóval ha valami fontosat akarunk tárolni, akkor használjuk inkább a d4-d7, és az a3-a5 regisztereket. Egyébként ezt sosem lehet biztosan tudni. A rendszerprogramozás során előbb-utóbb találkozni fogtok a struktúrákkal. Egy struktúra tulajdonképpen egy adathalmaz, ahol minden adatnak megvan a saját helye. Általában ha meghívunk egy rutint, és sok adatra van szüksége, akkor csak megadjuk a struktúra címét, és majd innen veszi az adatokat. Ennek egy fejlettebb változati az ún. TagList-ek. Ezek is struktúrák, de az egyes adatok helye nem kötött, hanem az adat előtt egy longword jelzi, hogy most mi is következik. Azt hiszem a struktúrák elég érthetőek mindenki számára, ezért inkább írok egy példát a TagList-ekre: ľScreenTags dc.l SA_Width,STDSCREENWIDTH dc.l SA_Height,STDSCREENHEIGHT dc.l SA_DEPTH,3 ... ...Ľ Ez egy ScreenTagList, és egy új képernyő megnyitásakor használjuk. Amikor a rendszerrutin elkezdi feldolgozni a struktúránkat, megnézi a következő longword-öt. Ez jelzi neki, hogy most milyen adat fog következni. Például itt először a képernyő szélességét állítja be, majd a magasságát, és végül a bitplane-ek számát. Ez azért kényelmesebb annál, mintha minden adatnak kötött helye lenne a listában. Na azt hiszem, ennyi elég is általánosságban a rendszerprogramozásról. Akkor most jöjjenek a konkrétumok. Kezdjük mindjárt az ˝exec.library-vel:Ľ Az exec gyakorlatilag a leglényegesebb LIBRARY. Az ő feladata a task-ok, a megszakítások és a különböző rendszerfeladatok elvégzése. Az egyik leglényegesebb rendszerrutin az OpenLibrary. Ehhez hasonló funkciójú az OldOpenLibrary nevű rutin. A különbség a kettő között az, hogy az OldOpenLibrary nem kéri a megnyitandó LIBRARY verziószámát, automatikusan a 0-t veszi verziószámnak. Ezzel szemben az OpenLibrary a D0-ban kéri a LIBRARY verziószámát. A másik paraméter amire a rutinnak szüksége van, a LIBRARY neve. Ez egy 0-ra végződő string a memóriában, és ennek a kezdőcímét kell megadni az A1-ben. Példát láthattatok rá a PoWeR #8-ban. Amit visszakapunk a D0-ban,az a LIBRARY báziscíme, amiről már volt szó. Ha nem ROM-library-t akarunk megnyitni, akkor bekéri a Boot-lemezt, és megpróbálja a LIBS alkönyvtárban megkeresni a kért LIBRARY-t. Ha ez nem sikerül, akkor 0-val tér vissza. A LIBRARY bezárása pont fordítva történik, és erre csak egy rutin van, a CloseLibrary. Itt az A1-be kerül a LIBRARY báziscíme, és ezután már hívhatjuk is a rutint. Ennyit a LIBRARY műveletekről. A következő fontos dolog az exec-ben a memóriakezelés. Ha például írunk egy programot, ami be akar tölteni egy file-t vagy csak egyszerűen memóriára van szüksége, akkor sok lehetőségünk van. Íme néhány: 1. Egyszerűen eldöntjük, hogy például $34546-tól miénk a szükséges memória. Ekkor többféle eredményt kaphatunk az első memóriamódositáskor: vagy kifagy a gép vagy nem, vagy csak nem úgy működik ahogy kéne. Ezt a módszert nem ajánlom senkinek, aki igaz barátja a rendszernek. 2. Használjuk a forráslistában a BLK.x direktívát a kívánt terület lefoglalására. Ez már jobb, de még mindig nem az igazi. Ugyanis ha egy változó méretű memóriarészre van szükségünk (tehát programírás közben még nem tudjuk a hosszát) akkor a lehetséges legnagyobb méretet kell lefoglalni, ami persze nem túl jó, gondoljunk csak bele, ha egy ismeretlen méretű file-t kell betölteni... 3. Elegánsan használjuk az exec erre készített rutinjait. Ez a legjobb módszer. Én most a 3. módszert magyarázom el részletesen. Az első dolog a memórialefoglalás. Erre 2 rutin is létezik, az AllocMem és az AllocAbs. Mindenekelőtt azt kell megérteni, hogy mi történik a lefoglalt memóriával. Nagyon egyszerű a válasz, ha mi nem nyúlunk hozzá, akkor semmi. Éppen az benne a jó, hogy a rendszer nem piszkálja, és lefoglaláskor csak olyat enged lefoglalni, amit ő nem használ, vagyis még szabad. Egyébként érdemes a memóriát rendszerbarát módon kezelni minden programunkban, még akkor is ha egy DOOM-szerű játékot írunk. Ugyanis ha csak simán, fixcímesen programozunk, felülírhatunk rendszerterületeket, és nem lehet majd GURU-mentesen kilépni a programból (Most nem az újságra gondoltam...). Tehát visszatérve a két rutinhoz, mindkettőben bemeneti adat a d0-ban tárolt hossz. Ez jelzi a lefoglalandó byte-ok számát. Az AllocAbs-nak még egy adatra van szüksége az A1-ben, ez pedig egy abszolút cím. Ettől a címtől kezdve foglal le memóriát nekünk. Persze nem biztos, hogy szabad ez a memóriaterület, ezért MINDIG meg kell vizsgálni a végeredményt!!! Ha esetleg 0-t kapunk vissza, akkor inkább próbálkozzunk máshol (eszünkbe ne jusson felszabadítani ezt a területet(!!!)). Ha nem 0-át kapunk vissza, akkor miénk a pálya, írhatunk, olvashatunk ezen a területen. A másik gyakrabban használt rutin az AllocMem. Itt a másik paraméter a d1-ben van. Ez sokfélét fog jelezni a rutinnak, az egyes bitek is mást jelentenek: ľ 00.bit: Publikus memória 01.bit: Chip-ram 02.bit: Fast-ram 16.bit: Memória törlése 17.bit: Legnagyobb blockĽ Szóval itt lehet beállítani, hogy milyen memóriát foglaljunk le, gondolom ez mindenkinek egyértelmű. Ha vége van a programunknak, nem árt ha felszabadítjuk a lefoglalt memóriát, mert esetleg két futtatás után nem lesz szabad memória. Erre a célra egy rutin létezik, ez a FreeMem. Kezelése értelemszerű, A1-be a kezdőcímet, D0-ba a hosszot kell berakni, majd meghívjuk a rutint. Akik 2.0-ás, vagy annál fejlettebb KickStarttal rendelkeznek, azoknak lehetőségük nyílik egy kényelmesebb memóriakezelés megvalósítására. Ezt támogatják az AllocVec, és az FreeVec rutinok. Mindkettőt ugyanúgy használhatjuk, mint az AllocMem, és a FreeMem rutinokat, de a fő különbség az, hogy a memória felszabadításnál nem kell emlékeznünk a méretre, az Operációs Rendszer megjegyzi helyettünk. Szóval az AllocVec használata megegyezik az AllocMem-ével, de a FreeVec-nél nem kell a d0-ban lennie a felszabadítandó memória méretének! Ez néhány esetben nagyon megkönnyíti a munkánkat, de nem mindig. Például ha lefoglalok egy jó nagy memóriablockot, majd úgy döntök, hogy a felét felszabadítom, akkor az AllocMem/FreeMem rutinokat célszerű használni. És végül nem árt, ha beszélünk az AvailMem rutinról. Ez nem csinál mást, csak a d1-ben megadott memóriatípus hosszát adja meg. Magyarul a bemeneti adat a d1-ben van, és ez az AllocMem/AllocVec rutinoknál is használt típust adja meg. Végeredményként megkapjuk a kérdéses memóriarész hosszát. Ehhez a rutinhoz egyébként nem kell 2.0-ás KickStart. Még egy pár jótanács: - Mindig nézzétek meg, hogy sikeres volt-e a memórialefoglalás, mert csúnya dolgok fognak történni, ha 0-tól felülírod a memóriát... - Csak olyan memóriát szabadíts fel, amit TE foglaltál le! - Csak olyan memóriát szabadíts fel, ami le van foglalva! Ja, remélem mindenki tudja, hogy mi a különbség a Chip- és a Fast-RAM között! Akkor ennyit a memóriakezelésről. Remélem minden érthető volt. A következő számban időlegesen elhagyjuk az exec-et, és a dos.library felé nézelődünk majd. Addig is valahogy bírjátok ki... ľ(Az említett cikk ebben a számban megtalálható - JaGu.)Ľ ˝COPĽ