MLM umožňuje vzít část paměti a její obsah zkopírovat na jiné místo paměti. Zápis takového příkazu je následující:
adresa1.adresa2 M adresa3
Obsah paměti od adresy 1 po adresu 2 (mínus 1 byte) se překopíruje na místo od adresy 3. Stejný obsah tedy potom bude na dvou místech.
Příklad:
E000.E200 M 3000
Zkopíruje znakovou sadu operačního systému do paměti RAM od adresy $3000.
Také velmi užitečná funkce. Syntaxe je podobná jako při kopírování:
adresa1.adresa2 V adresa3
Obsah paměti od adresy 1 po adresu 2 (mínus 1 byte) se porovná se stejně dlouhým úsekem paměti od cílové adresy 3. Pro každý byte, jehož hodnota se liší je vypsán 1 řádek obsahující zdrojovou adresu, hodnotu na zdrojovém místě a hodnotu na cílovém místě.
Příkaz pro plnění zadané části paměti má pouze MLM 2.3. Jeho syntaxe je následující:
adresa1.adresa2 = hodnota
Obsah paměti od adresy 1 po adresu 2 (mínus 1 byte) bude vyplněna zadanou hodnotou, která musí být v rozsahu 0 až 255. Hodnotu lze zadat pouze jednu, takže není možné vyplnit takto část paměti opakující se skupinou hodnot.
Tuto nevýhodu lze ovšem obejít jednoduchým trikem. Ten současně umožňuje vyplňovat paměť i v MLM 2.1.
Vysvětlíme si to na příkladu. Řekněme, že chceme oblast od $3000 po $30FF vyplnit posloupností hodnot $AA $BB $CC. Začneme tím, že na adresu $3000 (až $3002) tyto hodnoty ručně vložíme:
3000;AA BB CC
Nyní potřebujeme nakopírovat hodnoty z $3000 až $3002 periodicky do oblasti od $3003 po $30FF. Ačkoli to nezní intuitivně, udělá to za nás následující příkaz:
3000.30FD M 3003
To "30FD" není překlep. Protože kopírujeme posloupnost o délce 3 byty, musíme počítat s tím, že nám přeteče o 2 byty ($30FE a $30FF) za zadanou cílovou adresu (tj. $30FD). Kdybych tam nechal $30FF, přepsaly by se ještě adresy $3100 a $3101, což nechceme.
1 byte (hodnotu uloženou v $3000) bychom rozkopírovali do stejné oblasti takhle:
3000.30FF M 3001
5 bytů pak takto:
3000.30FB M 3005
Pravidla lze zobecnit následovně. Před tečku uvádíme adresu, od které budeme vyplňovat a kde současně leží počátek vyplňovaných hodnot. Za tečkou uvedeme adresu, kterou již nechceme přemazat, ovšem poníženou o délku (počet bytů) kopírované posloupnosti. Tuto délku musíme naopak přičíst k počáteční adrese a výsledné číslo uvedeme za M.
Vyplňování paměti lze samozřejmě použít i pro její mazání, a to tak, že určitou oblast vyplníme nulami (tedy ne znakem 0, ale hodnotou $00). Pokud nějakou oblast zkopírujeme a původní místo pak smažeme, docílíme vlastně přesunu původního obsahu.
MLM je také jen program. Sice uložen v paměti ROM, přesto potřebuje pro svůj běh několik desítek bytů v paměti RAM. Z principu věci není vůbec dobrý nápad hodnoty na těchto adresách měnit. A které to jsou?
MLM 2.1 využívá tyto části RAM:
MLM 2.3 využívá tyto části RAM:
Vedle práce s pamětí umí MLM načíst či zapisovat i data na disku. Tyto operace není možné provádět po bytech. Je nutné pracovat s celými sektory.
Sektor má v případě formátů single a medium délku 128 bytů. U formátů double a quad (DS/DD) mají sektory 256 bytů. Sektory jsou číslovány od 1.
Načítají se sektory z disketové jednotky 1, a to od uvedeného sektoru až dokud není dosaženo zadaného počtu načtených sektorů. Všechna načtená data se (byte po bytu) zapisují do paměti od určené adresy.
Syntaxe je následující:
adresa<od_sektoru.počet_sektorů
Příklad:
4000<100.12
Načte 12 sektorů počínaje sektorem 100 a získaná data ukládá od adresy 4000.
MLM zapíše obsah paměti od určené adresy v rozsahu stanoveném počtem sektorů na disketu č. 1. Počet sektorů musí být menši než 256, přičemž hodnota 0 znamená 255.
Syntaxe příkazu:
adresa>od_sektoru.počet_sektorů
Příklad:
4000>100.12
Zapíše data uložená v paměti od adresy 4000, a to v rozsahu 12 sektorů (tj. 1536 bytů ve formátu single nebo medium) počínaje sektorem 100.
Vedle 65536 bytů operační paměti existuje ještě jedno místečko, kde lze uchovávat trošku informací. Tímto místečkem jsou registry přímo v procesoru 6502. Jde o pouhých 7 bytů rozdělených do 6 "chlívečků", zvaných registry.
Tyto registry nemají (na rozdíl od bytů v paměti RAM) adresy, ale jména. Jsou označeny X, Y, akumulátor, stavový registr (SR), ukazatel zásobníku (SP) a programový čítač (PC). Programový čítač má délku 16 bitů (2 byty), zatímco ostatní registry jsou 8bitové.
Registry mají specifický význam pro běh každého programu. V assembleru se používají např. pro početní operace či k podmíněným skokům. Více o assembleru si můžete přečíst např. v knize [9], více o registrech procesoru pak v knize [10].
MLM 2.3 pracuje kromě registrů procesoru 6502 ještě s registrem řízení paměti, který je zajišťován obvodem PIA 6520. Tento registr je dostupný na adrese 54017 ($D301) a je označován jako PORTB (protože u Atari 400 a 800 obsluhoval 3. a 4. joystickový port).
U počítačů s přídavnou pamětí (včetně 130 XE) je PORTB používán k řízení práce s touto pamětí. Protože rozšířenou paměť není možné adresovat přímo, vezme se její část (16 KiB) a tou se překryje vyhrazená část operační paměti (adresy 16384 až 32767, tj. $4000 až $7FFF).
Podrobnější informace o registru PORTB lze najít např. v knize [2], strany 1 až 3, nebo v knize [5], strany 49 až 52.
Ke zobrazení obsahu všech registrů slouží jednopísmenný příkaz "R". V MLM 2.3 vypadá výstup takto:
PC MEM AC XR YR NV-BDIZC 0000 FF 00 00 00 00
Význam jednotlivých hodnot (zleva):
PC = programový čítač, MEM = reg. řízení paměti, AC = akumulátor, RX = registr X, RY = registr Y, NV-BDIZC = stavový registr.
Výstup MLM 2.1 se liší pouze tím, že v něm chybí sloupec MEM. Hodnoty registrů jsou vždy zobrazeny hexadecimálně (bez ohledu na zapnutý číselný režim).
Hodnotu v některých registrech lze přímo měnit. V MLM toho docílíme zapsáním jednopísmenného označení registru, rovnítkem a 8bitovou hodnotou (0-255, resp. $00-$FF), kterou do něj chceme vložit.
Označení registrů v MLM je následující:
W - akumulátor X - registr X Y - registr Y P - stavový registr M - registr řízení paměti (jen v MLM 2.3)
Pokud tedy chceme do registru X vložit hodnotu $A0, napíšeme X=A0 a stiskneme Return. Hodnotu programového čítače přímo měnit nelze.
V MLM 2.3 není možné přímo měnit hodnotu na adrese 54017 ($D301). Změnu hodnoty PORTB lze docílit právě jen pomocí nastavení registru M.
Paměť počítače může obsahovat různé typy dat: čísla, text, obrázky, zvuky. Prostě cokoli, co se dá přepsat do číselné (digitální) podoby.
Speciálním druhem dat v paměti jsou instrukce strojového jazyka, neboli program. Jde o posloupnost příkazů pro procesor, z nichž většina je doplněna o parametry (např. adresa paměti, ze které se má číst hodnota).
Každá instrukce (resp. její identifikátor) zabírá v paměti 1 byte. Bezprostředně za instrukcí následují její parametry, také jednobytové hodnoty. Každý typ instrukce má přitom počet parametrů přesně stanoven, takže procesor ví, kolik jich má přečíst.
Hned za posledním parametrem první instrukce následuje k˘dové označení další instrukce a její parametry. A tak to jde pořád dál, dokud program neskončí.
Program se do paměti může dostat různými způsoby. Jednou z možností je vložit jej tam ručně. Další možností je načtení z disku, cartridge či jiného paměťového média.
Běh programu potom vypadá tak, že procesor načte první příkaz a vykoná jej s použitím jeho parametrů. Těch ví, kolik je, takže následně skočí za ně, kde najde další příkaz, který vykoná, skočí za jeho parametry atd.
Jak ale procesor ví, kdy a hlavně odkud má začít číst instrukce? To je součást procesu, kterému říkáme spuštění programu neboli skok na adresu.
MLM k tomu používá příkaz GO, před který je nutné napsat adresu, od které má procesor začít programový k˘d vykonávat.
Pokud tedy máme strojový program uložený v paměti od adresy $3000, spustíme jej příkazem
3000 GO
Program potom běží, dokud nenarazí na svůj konec (instrukce RTS) nebo dokud uživatel nestiskne Reset (nebo nevypne počítač). Narazí-li program na RTS, vrátí se zpět do MLM.
Tato nová a zajímavá funkce je dostupná pouze v QMEGu 4. Freezer (znamená anglicky "mrazák") způsobí, že běh procesoru převezme pod kontrolu QMEG. Do té chvíle běžící program přitom jakoby zamrzne - obraz i zvuk zůstanou zaseknuté.
K čemu je to dobré? Zamrznutý obsah paměti (zpravidla při běhu nějakého programu) lze pozměnit nebo odložit do rozšířené paměti. Odtud lze paměť uložit na disk a někdy později obnovit stav přesně v okamžiku zamrazení.
Tato funkce je pojmenována po známém příkazu POKE z Basicu. Pro jistotu připomenu, že POKE slouží k uložení hodnoty do paměti, neboli změně obsahu konkrétního bytu paměti.
Takže Freezer-Poke nám umožní po zmrazení běžícího programu změnit libovolný byte v paměti RAM a "odmrazit" program, aby mohl dále pokračovat.
Pokud chceme tuto funkci využít, nejprve spustíme požadovaný program a uvedeme jej do stavu, kdy chceme provést změnu.
Nyní musíme program zmrazit, což provedeme kombinací kláves Control+Help. Aktivace freezeru je avizována krátkým zvukem. Pokud zůstává znít zamrazený zvuk programu, můžeme jej vypnout pomocí mezerníku.
Nyní můžeme začít měnit obsah paměti. Každá změna se zadává sekvencí šesti hexadecimálních číslic (tj. znaky 0 až 9 a A až F). První 4 zadané číslice představují adresu paměti a poslední 2 pak hodnotu, která se má na danou adresu zapsat.
Zadávané hodnoty se nezobrazují. Jednotlivé stisky kláves jsou ale avizovány krátkým zvukem. Pokud se dopustíme překlepu, můžeme posledně zadanou číslici smazat klávesou Delete.
V případě potřeby je možné smazat i celou (dosud neodeslanou) sekvenci, a to klávesou Clear.
Pokud šestici zadáme úspěšně (nebo si to aspoň myslíme), odešleme ji ke zpracování. Jak jinak než Returnem. Změna se okamžitě provede.
Nyní můžeme pokračovat další změnou paměti, tj. zadáním další šestice, nebo ukončit freeze klávesovou zkratkou Control+Help či jenom Help.
Prakticky si to můžeme ukázat např. na hře Qausimodo. Nejprve hru nahrajeme. Na úvodní obrazovce zmáčkneme Control+Help, zadáme šestici 2DB300, potvrdíme Returnem a odmrazíme Helpem. Nyní můžeme hru Startem spustit a jsme nesmrtelní!
Druhým způsobem využití freezeru je uložení celé operační paměti do ramdisku. Později můžeme takto uložený obraz paměti načíst zpět do RAM a tím vrátit počítač do stavu v okamžiku uložení.
Asi není třeba upozorňovat, že při ukládání obrazu paměti bude obsah ramdisku přepsán.
Jak na to? Až dostaneme počítač do stavu, který chceme uložit, nejprve aktivujeme freezer známou kombinací Control+Help.
Paměť do ramdisku uložíme klávesovou zkratkou Control+S. Operace trvá zhruba 2 sekundy. Systém odmrazíme opětovným stiskem Control+Help (nebo jen Help).
Budeme-li chtít stav paměti z ramdisku obnovit, postupujeme obdobně. Nejprve aktivujeme freezer (Control+Help), následuje klávesová zkratka pro načtení (což je Control+L) a operaci ukončíme stiskem Control+Help nebo Help.
A do třetice ještě jedna funkce související s ramdiskem - výměna. QMEG totiž umí v režimu freezeru zaměnit obsah operační paměti a ramdisku, tj. co bylo v RAM přesune se do ramdisku a opačně. K tomu slouží klávesová zkratka Control+E.
Všechny tři funkce, tak jak jsme je popsali (tj. s použití klávesy Control), pracují s prvním ramdiskem, označovaným písmenem X.
Pokud však máme k dispozici paměti více (128 nebo 192 KiB), můžeme ji rozdělit do 2 ramdisků (X a Y) a potom pro Freezer využít i druhou část (Y).
Princip fungování je stejný jako při využití ramdisku X. Jediný rozdíl je v klávesových zkratkách. Místo Control se používá Shift, tj. Shift+S (ulož do Y), Shift+L (načti z Y) a Shift+E (vyměň obsah RAM a Y).
Ještě jedno upozornění: Program obnovený načtením z ramdisku nemusí fungovat dokonale. Stav počítače totiž vedle obsahu paměti definují i hodnoty hardwarových registrů. Ty ovšem spolu s pamětí uloženy nejsou.
Dalším omezením jsou programy (např. některé hry nebo dema), které vypínají operační systém. Ty pak samozřejmě služeb OS (včetně QMEGu a jeho freezeru) využívat nemohou.
Uložení stavu (moderně bychom řekli snapshotu) do ramdisku je hezké, ale co když chceme uchovat tento "snímek" na delší dobu než do vypnutí počítače? Můžeme si ramdisk zapsat na externí disk.
Toho docílíme v menu QMEGu bez zapnutého freezeru (tj. bez Control+Help). Stačí prostě klávesy "R" a "W", jak bylo popsáno v prvním díle tohoto textu (část 2.8.1 a 2.8.2).
Lepší je ovšem použít Shift+W (pro zápis) a Shift+R (pro načtení). Tak dojde k zapsání, resp. načtení, pouze nezbytného počtu sektorů. Rozdíl je patrný také ve stavovém řádku, kde se vpravo zobrazí navíc písmeno F (jako Freezer). Použití Shift+W a Shift+R je nezbytné pro počítače s pouze 64 KiB rozšířené paměti (typicky 130 XE).
Shift+R a Shift+W (stejně jako "R" a "W") berou jako cílový, resp. zdrojový, vždy jen ramdisk X. Chceme-li ovšem přesunout obsah X (uložený ve freezeru pomocí Control+S) do Y, najedeme kurzorem na disk přidělený Y (defaultně 7 a 8), stiskneme Shift+W a následně Start. Naopak pro přesun obsahu z Y do X najedeme na Y a stiskneme Shift+R.
Uložení zmrazené paměti z X na disketu provedeme tak, že najedeme kurzorem na příslušný disk (např. 1), stiskneme Shift+W a potom Start. Pro načtení uložené paměti v budoucnu najedeme na jednotku s uloženým obsahem a stiskneme Shift+R (následovaný startem).
A to je pro tentokrát vše, přátelé.
Bohdan Milar
2018
[2] Ramdisk (práce s rozšířenou pamětí); R. Kudla, Z. Burian, L. Burian. 1992. Flop, Rožnov pod Radhoštěm [4] Adresy paměti počítačů ATARI 600 XL/800 XL 1; P. Dočekal. 1987. ČSVTS OKP Liberec [5] Adresy paměti počítačů ATARI 600 XL/800 XL 2; P. Dočekal. 1987. ČSVTS OKP Liberec [9] Asembler; R. Kudla. 1992. Flop, Rožnov pod Radhoštěm [10] Mikroprocesor 6502 - popis instrukcí. 1992. Atari klub Olomouc [11] ATARI Manuály II; I. Drastich. 1989. Klub mikroelektroniky při ČSVTS Ostrava [12] Flop Bulletin 2/94. 1994. Flop, Rožnov pod Radhoštěm