ZAČÍNÁME S MOTOROLOU
Ahoj (budoucí) programátoři, náš systémový seriál se opět hlásí o slovo! V
minulém (tedy prvním) díle našeho nového seriálu jsme si slíbili, co všechno se
budeme učit a teď je na čase, abychom sliby začali plnit. Především bych vás rád
upozornil že slíbený druhý seriál o programování samotné MOTOROLY se zatím z
technických důvodů nekoná a pravděpodobně ani v nejbližší době konat nebude. Z
toho plyne nejen ponaučení "Nechval dne před večerem", ale i fakt, že se oblast
tohoto seriálu rozšiřuje i sem. Ale nebojte se, o nic nepřijdete, rozšiřuje se
tématický okruh - rozšíříme i délku jednotlivých dílů.
Takže, jdeme na to. Pro ty z vás, kteří nemají o assembleru ani tušení,
začneme od píky. Srdcem vaší AMIGY (a nejen vaší AMIGY, ale i spousty jiných
AMIG, MACů a "EsTéček") je procesor řady MOTOROLA. Pokud máte A500 nebo A2000,
je to MC68000, pokud máte A1200, pak je vaším srdcem MC68020, a jestli jste na
tom lépe - t j. A3000, A4000 nebo A500/A1200 s některou s lepších turbokaret,
máte v označení vašeho procesoru čísla 68030 nebo 68040. Co to znamená pro vás
jako pro programátora? V celku nic zvláštního. Všechny tyto procesory jsou mezi
sebou v podstatě kompatibilní, s tím že 68020 a vyšší mají specielní adresovací
režimy a instrukce, kterými se však pro začátek nebudeme zabývat. Další rozdíl
je v adresování paměti, ale o tom až za chvilku.
1. Základní údaje o MOTOROLE
Když otevřete váš počítač a budete MOTOROLU hledat, najdete podlouhlý
obdélníček, případně malinký čtvereček se spoustou nožiček okolo. Nebudeme se
podrobně zabývat tím, co která dělá, to bychom si mohli udělat další seriál -
zaměříme se pouze na tzv. adresové a datové signály. Pokud si chcete alespoň
zjednodušeně představit, jak přibližně takový počítač funguje, zkuste to třeba
takhle : Procesor nastaví na adresové signály adresu paměti, ze které chce číst
a paměť mu na datové signály pošle číslo, které v paměti na dané adrese leží.
Proč vám to tu vykládám? Jen proto, abyste si uvědomili rozdíl mezi procesory
68000 a 68020(+vyšší). Těch datových signálů má totiž 68000 jen 16, zatímco
68020+ jich má 32. To má za následek, že v jednom okamžiku (hodinovém cyklu) je
mezi pamětí a procesorem najednou přeneseno dvakrát tolik informací, než u 68000
- říkáme, že procesor je plně dvaatřicetibitový. Naproti tomu MC68000 přenese v
jednom hodinovém cyklu pouze 16 bitů, a takovým procesorům říkáme ...?? No? Jak
byste řekli? Šestnáctibitové? Chyba ! Říkáme jim "procesory s šestnáctibitovou
vnější architekturou". Proč? Jednoduché vysvětlení. Programování obou procesorů
je stejné - oba mají dvaatřicetibitové registry a instrukce, které s nimi
operují, neboť jednou instrukcí jsou schopny přenést 32 bitů - mají
dvaatřicetibitovou vnitřní strukturu. Pro srovnání, procesory INTEL 8086 a 80286
jsou procesory plně šestnáctibitové - mají šestnáctibitovou vnější i vnitřní
strukturu, procesor 80386 SX je již na úrovni MC68000 - je vnitřně 32bitový,
ovšem má pouze 16 dat. Od 386DX jsou již INTELy plně 32bitové, tedy jako
MOTOROLA 68020 a lepší. Nevýhoda spočívá v tom, že většina software na PC je
psána tak, aby fungovala i na 286, t j. šestnáctibitově, takže 32-bitová
struktura zůstává nevyužita ... ale vraťme se k MOTOROLÁM. Další důležitá věc,
na které záleží rychlost prováděného programu, je hodinová frekvence procesoru.
U 68000 to bývá 7 nebo 14 Mhz, u 68020 14MHz nebo 28Mhz a u lepších procesorů
bývají frekvence 25, 33 nebo 50 MHz. Frekvenci nebudeme příliš rozebírat, v
zásadě platí, že čím vyšší frekvence, tím větší výkon, ovšem pouze u přesně
stejného typu procesoru.
2. Registry
Registry si můžete představit jako polička, do kterých si můžete ukládat
čísla. Všechny registry v MOTOROLE jsou dvaatřicetibitové, což znamená, že do
nich můžete ukládat čísla 0 až 2 na 32 -1, čili 0 až 4,294,967,295. Tedy rozsah
něco přes čtyři miliardy (mám dojem, že to pro většinu číselných operací celkem
postačuje). Pokud chcete používat i záporná čísla, číselný rozsah je -2 na 31-1
až +2 na 31 -1 , tedy -2,147,483,647 až +2,147,483,647. Základních registrů je
šestnáct, osm datových a osm adresových, značí se D0, D1, D2, D3 ... D7, a A0 až
A7 (hádejte které jsou datové a které adresové). Do adresových registrů se
ukládají většinou adresy, do datových kupodivu data. Přesuny a matematické
operace s registry jsou mnohem rychlejší než operace s pamětí, takže je vždy
výhodnější použít registr než paměť. Ovšem počet registrů není nekonečný,
dokonce by se dalo říci že má k nekonečnu hodně daleko, takže registry používáme
pouze na data ke kterým se přistupuje nejčastěji anebo tam, kde instrukce přímou
operaci s pamětí nedovolují. Kromě datových a adresových registrů máme ještě
tzv. Status Register (zkratka SR, to by jednoho nenapadlo). Jeho jednotlivé bity
reprezentují příznaky procesoru a některé stavy procesoru, o kterých si povíme
později. Do SR jako systémoví programátoři abych tak řekl "nemáme co kecat",
jinými slovy, pokud běžíme jako úloha pod systémem amigy, nemáme k SR přístup
zápisu, což nás ovšem vůbec nemusí mrzet, protože zapisovat do SR pod systémem
skutečně není potřeba (kdyby bylo, systém by to asi dovolil, že ano). Registr A7
je také označován jako Stack Pointer, tedy ukazatel na zásobník. Zásobník je
taková moc chytrá věcička, pro kterou je vyhrazena část paměti, a do které
můžete skladovat data. Jelikož poslední číslo, které jste do zásobníku vložili,
zůstává na jeho vrcholu a při vybírání půjde také první ven, říkáme, že zásobník
je typu LIFO - Last In, First Out. Pokud si to nedokážete představit, je to něco
jako když se cpou lidi do autobusu - poslední dovnitř, první ven. Rád bych zde
ještě upozornil na jednu věc. Procesor má dva režimy - User mode a Supervisor
mode. V Supervisoru pracuje systém, aplikace jedou pod Userem. Aby měl každý mód
oddělený zásobník, existuje ještě jeden registr - SSP (Supervisor stack pointer)
který ukazuje na zásobník supervisoru. V user mode nejsou přístupné některé
registry (např. právě SSP) a některé instrukce (např. zastavení procesoru nebo
RESET).
3. Paměť
Paměť, jak by vás už pomalu mohlo napadnout, je taková ta věc, která si něco
pamatuje. Tvoří jí jednotlivé bajty (nebo chcete-li bytes), které se, vzhledem k
tomu že jich bývá hodně, počítají na Kilobajty anebo na Megabajty, což záleží
zejména na obsahu vaší peněženky. Jeden bajt, anglicky psáno byte, se sestává s
osmi bitů (anglicky psáno bits). Čili do jednoho bajtu nacpete číslo od nuly do
2 na 8 -1, neboli 0 - 255; zase, pokud použijete znaménko, je to -128 až +127.
Kilobajt nemá 1000 bajtů, jak by se možná mohlo zdát, ale má jich 1024, zrovna
tak jako megabajt má 1024 kilobajtů, nebo kilobytes, jak se to komu líbí. Je to
proto, že ve dvojkové soustavě se přece jen 1024 vyjadřuje o moc lépe než 1000.
Bajty se dále sdružují do wordů (word = 2 bytes) a do longů (long = 4 bytes = 2
words). Jelikož registr procesoru je, jak už víme, long, lze ho zapsat do paměti
do čtyř bajtů, neboli do dvou wordů. Aby se nezapomnělo, který bajt si co
vlastně pamatuje, má každý bajt svojí adresu. Neznamená to, že by jeden bajt měl
třeba "Čkalova 25, Praha 6", ale prostě každý má své číslo, od nuly do konce
paměti, kterému nadneseně říkáme adresa, aby si ostatní mysleli, že tomu
rozumíme. Na amize se paměť dělí na tzv. CHIP-RAM a FAST-RAM. Do CHIP-RAM mají
kromě procesoru přístup i ostatní čipy amigy, což pro vás prakticky znamená, že
v CHIP-RAM může být umístěn obraz, zvuk (sampl), sprite (pohyblivý objekt, např.
šipka myši), buffer pro DMA disku a podobné nesmysly. Naproti tomu do FAST-RAM
má přístup pouze sám procesor, ovšem tato paměť se vyznačuje oproti CHIP-RAM
mnohem vyšší rychlostí. Na A500 se tento rozdíl nijak neprojevuje, jelikož to,
co je na interních kartách do A500 vydáváno za FAST-RAM, podléhá vnitřnímu
řadiči CHIP-RAM, takže tato paměť je nejen stejně pomalá, ale navíc do ní může
pouze procesor. Naproti tomu u A1200 je FAST-RAM opravdu fast, program v ní běží
cca 2x rychleji než v CHIP-RAM, a pokud máte turbokartu, můžete dosáhnou i
výrazně většího urychlení. Velikost CHIP-RAM je omezena adresovacím prostorem
čipu AGNUS (u AGA čipů ALICE), který činí u nejstarších A500 512 kB, u novějších
A500 a A2000/3000 1 MB a u ECS a AGA strojů (A500+, A600, A1200, A4000) 2 MB.
Velikost FAST-RAM je omezena pouze adresovacím prostorem procesoru, který je
nepoměrně větší (rozhodně si nemusíte dělat starosti, že byste ho někdy zaplnili
pamětí).
4. Instrukce
Nebudeme se zde zabývat podrobným popisem úplně všech instrukcí procesoru,
pro začátek si ukážeme pár základních, se kterými budeme muset pro začátek
vystačit. V některém s pokročilejších dílů pak uvedeme tabulku se všemi
instrukcemi, dobou trvání a stručným popisem. Napřed si řekneme o instrukcích
motoroly něco obecně. Taková jednoduchá instrukce vypadá například takto: MOVE.L
#1000,d0. První část instrukce před tečkou, "MOVE", určuje, co se vlastně bude
dít - v tomto případě přesun dat. Přípona ".L" určuje šířku dat, na které se
instrukce vztahuje - v tomto případě LONG, tedy 32 bitů. Přípona může mít ještě
tvar ".W" nebo ".B", což znamená WORD (16 bitů) anebo BYTE (8 bitů). Pokud
příponu nenapíšete vůbec (ani tečku), automaticky se počítá, jako byste napsali
".W". Po příponě následují dva parametry, které jsou na MOTOROLE řazeny oproti
většině ostatních procesorů naopak (ale zato mnohem logičtěji) - první je
zdrojový operand, následuje pak cílový. Prostě řečeno, tisíc do dénuly.
Jednoduchá nemotechnická pomůcka - místo čárky si vždy řekněte "do" a víte o co
jde. Čili dostali jsme se k tomu, že jsme naplnili celý registr d0 číslem 1000.
Ten křížek "#" je tam proto, aby se poznalo, že se jedná o určité číslo,
konstantu. Pokud bychom ho tam nenapsali, instrukce by vypadala MOVE.L 1000,d0 ,
což by ovšem znamenalo: Vezmi LONG na adrese 1000, a dej ho do D0. Čili důležitý
poznatek - číslo samotné znamená vždy adresu, číslo začínající "#" znamená
konstantu, tedy to určité číslo. Nyní se ještě vraťme k bajtům, wordům a longům.
Řekli jsme si, že paměť je řada bajtů, z nichž každý má svou adresu. Jak se do
takové paměti zapisují wordy a longy ? Nejprve si vysvětlíme šestnáctkovou
(hexadecimální) a dvojkovou (binární) soustavu a jejich souvislost s pamětí.
Desítková soustava, ve které počítáme my všichni zcela normálně se sestává z
číslic 0-9 (tedy deseti, odtud desítková). Pokud nám nestačí jedna číslice,
přidáme další (zleva), která bude vyjadřovat, kolikrát se "přetočila" první
číslice. Když počítáme do deseti, 1,2,3 ... 9, dostáváme se k devítce a
přičítáme opět jedničku, první číslice "přeteče" a ukazuje zase nulu. Přidáme
druhou, která ukazuje, kolikrát už ta první přetekla, v našem případě 1. Tedy
máme číslo 10. Teď si představte, že ve dvojkové soustavě máme pouze číslice 0 a
1 (vevnitř počítače jsou reprezentovány signály vypnuto a zapnuto, na drátě je
napětí a nebo ne). Počítání bude vypadat podobně : 0,1, a co teď ? Další číslice
už nemáme, takže první přeteče (na nulu) a přidáme druhou, která bude ukazovat,
kolikrát první přetekla a máme výsledek - 10. Takže počítáme dál 0, 1, 10, 11,
(přidáváme číslici) 100, 101, 110, 111 .. atd. Samozřejmě třetí číslice ukazuje,
kolikrát přetekla druhá, čtvrtá ukazuje kolikrát přetekla třetí a tak dál. Jako
u desítkové. Čili, číslo 4 je ve dvojkové soustavě reprezentováno číslem 100,
číslo pět číslem 101 atd. Každá číslice (0 nebo 1) představuje jeden bit. Pokud
máme k dispozici bity třeba 4, můžeme pomocí nich vyjádřit čísla 0-15. 0000 bude
0, a 1111 bude 15. Pomocí kombinatoriky lehce zjistíme, že maximální
vyjádřitelné číslo se rovná dvojce umocněné počtem bitů, minus jedna. Tedy pokud
máme bitů 8 (jeden byte), můžeme vyjádřit 2 na 8 = 256 kombinací, tedy 0 - 255
(proto -1, musíme počítat i nulu). Ovšem vyjadřovat ve dvojkové soustavě čísla
kolem miliónů už není to pravé ořechové, a proto vznikla soustava šestnáctková
neboli hexadecimální. Kromě číslic 0-9 používá ještě písmena A-F. Tedy počítáme
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11,12 ... atd. Všimněte si, že číslo, které
maximálně vyjádříme jednou číslicí je F, tedy 15, což odpovídá maximálnímu číslu
vyjádřenému čtyřmi bity. Pokud chceme tedy vyjádřit jeden byte, použijeme dvě
číslice a máme rozsah 0 - FF (0 - 255), tedy přesně rozsah jednoho byte. Proč to
všechno? Nebuďte nedočkaví, všechno se dozvíte. Vrátíme se zpátky k vyjádření
wordu dvěma bajty. Představte si, že chcete do paměti zapsat číslo 258, tedy o 3
víc, než je rozsah jednoho byte. Napíšete třeba instrukci MOVE #258,10000. Jak
už víme, tato instrukce zapíše číslo 258 na adresu 10000. Jelikož jsme neudali
příponu, bere se automaticky ".W", tedy word. Ovšem na adrese 10000 je byte
jenom jeden, takže ten druhý se automaticky zapíše na adresu 10001. Ale teď, jak
se číslo 258 rozloží na 2 bajty? Počítejte se mnou. 253, 254, 255 .. a co teď?
256 už nejde, čili přenulujeme a zvýšíme druhý bajt o jedničku. Takže máme (oba
bajty): 0 255 (255) , 1 0 (256), 1 1 (257), 1 2 (258). Číslo 258 se do paměti
zapíše jako 1 a 2. Neboli, na adresu 10000 se uloží 1, na adresu 10001 se uloží
2. Teď si to zkusme v hexu, tedy v šestnáctkové soustavě. Číslo 255 = $00FF, 256
= $0100, 257 = $0101, 258 = $0102 (znak dolaru se píše před hex číslo proto, aby
se poznalo, že se jedná o číslo v šestnáctkové soustavě). Vidíte to? Číslo $0102
se rozloží na bajty $01 a $02. V desítkové soustavě nepoznáme, že se 258 rozloží
na 1 a 2, naproti tomu v šestnáctkové je to vidět poměrně jasně - $0102 se děli
na $01 a $02. Pokud instrukci napíšeme takto: MOVE #$0102,10000, můžeme ji
interpretovat jako Ulož číslo $0102 na adresu 10000, neboli ulož $01 na 10000 a
$02 na 10001. Nechápete? Nevadí, přečtěte si odstavec ještě několikrát, třeba to
pomůže. Pro ty z vás, kteří již psali v assembleru, ale na jiném typu procesoru,
připomínám, že u MOTOROLY je řazení bajtů obrácené, tedy od nejvyššího k
nejnižšímu, tj. LONG $12345678 se do paměti zapíše jako posloupnost bajtů
$12,$34,$56,$78 a nikoliv, jako je tomu třeba u INTELů, $78,$56,$34,$12. Máto
své výhody i nevýhody. Výhoda spočívá v tom, že pokud se podíváte na danou
adresu, vidíte posloupnost bajtů rovnou jako hotové číslo. Nevýhodou je, že vždy
musíte vědět, jakého typu je operand, jinak přečtete nesmysl. Příklad: MOVE.L
#100,10000 uloží na adresu 10000 long 100, ale pokud se podíváte na adresu
10000, najdete tam nulu, jelikož nejvyšší bajt longu 100 je nula. Čili MOVE.B
10000,d0 nedá do D0 stovku, jak by tomu bylo v případě ostatních procesorů, ale
nulu. Který z uvedených způsobů je lepší, to už je otázka zvyku a názoru.
Instrukce uložené do paměti tvoří program. Takovýto program si představte jako
řadu čísel (bajtů), kterou postupně procesor projíždí a vykonává. Abyste
nemuseli psát program přímo v číslech, máte ASSEMBLER, což je program
zajišťující překlad instrukcí, tedy v podstatě slov která píšete, do čísel
(bajtů), které se pak zapíší na určitou adresu a spustí. Spouštěcí adresa je
samozřejmě vždy různá, při spuštění programu se prostě najde první volné místo,
do kterého se program plácne. Některé jednoduché programy fungují od kterékoliv
adresy, avšak většina programů ne. Takovéto programy assembler překládá tak,
jako kdyby měly být uloženy od adresy 0 a přidává k nim tzv. relokační tabulku.
Systém po nahrání programu do paměti použije tuto tabulku k modifikaci programu
tak, aby program fungoval přesně od adresy, na které se zrovna nachází.
5. Něco o systému
Operační systém amigy je velice unikátní věc, kterou je třeba respektovat.
Hlavní věc, na kterou si při programování musíte dát pozor, je multitasking
(několik programů běžících zároveň). Jak je uděláno, že v jednom okamžiku běží
najednou třeba deset programů, o to se zatím nestarejte, v podstatě jde o velice
rychlé přepínání; podrobný výklad se opět dozvíte později. Pro vás je důležité,
že to tak je a že to musíte respektovat (pokud ovšem nechcete, aby váš program
vypadal jako aplikace pod MS-DOSem, neřkuli Windows). Pokud jste už někdy
(nejen) v assembleru něco psali, následující řádky jsou určeny přesně pro vás.
Základní pravidla pro programování v multitasku:
- Nikdy nepoužívejte smyčky při čekání (ať už na klávesu, myš, nebo cokoliv
jiného). Basicovské 10 IF INKEY$="" THEN GOTO 10 je ABSOLUTNĚ NEPŘÍPUSTNÉ! Když
na něco chcete čekat, použijte službu systému.
- Pokud chcete, aby byl program nějakou dobu neaktivní, např. počkal 2 sec,
nikdy nedělejte čekací smyčky! Vždy si zavolejte službu systému DELAY nebo
podobnou!
- Nepřistupujte přímo na hardware amigy. Riskujete tím konflikt s ostatními
běžícími programy, nekompatibilitu s ostatními počítači a mnohdy i zhroucení
systému. Když už používáte hardwarové registry, snažte se používat jenom ty, co
jsou na čtení. Pokud musíte (naprosto v krajním případě !) používat i ty
ostatní, uvědomte o tom systém (např. OwnBlitter) anebo ho vůbec zakažte
(uživatelé vás ale ani trošku nebudou mít rádi ...)
- Nelezte do systémových struktur. Tedy číst je můžete, od toho tam jsou, ale
zápis se důrazně nedoporučuje. Pokud vám připadá, že je dobrý nápad otvírat okno
tak, že jeho strukturu přidáte do seznamu oken, místo toho abyste zavolali
službu OpenWindow, pak při programování tvrdě narazíte. Obzvláště budete-li
disponovat nápady podobného ražení i nadále.
Našlo by se spousta dalších, ale povíme si je až při konkrétních příkladech. V
podstatě platí zásada použijte systémové služby, kde to jenom jde. Když už si
myslite, že na to co potřebujete, žádná systémová služba není, pročtěte si ještě
jednou celý seznam služeb systému. Určite ji tam někde objevíte.
6. Začínáme programovat
Následuje popis assembleru AsmOne nebo TrashmOne, který budeme v našem
seriálu používat. Pokud máte jiný assembler a umíte ho ovládat, můžete
samozřejmě pracovat i s ním.
Při spuštění asembleru jste dotázáni, kolik paměti má být vyhrazeno pro vaše
programy + zdrojové texty a o jakou paměť se bude jednat. Na první otázku (typ
paměti) stiskněte enter (vezme se ta, které je víc). Protože budeme ze začátku
dělat jednoduché programy, na druhou otázku odpovězte třeba 100 a jste v
assembleru. Klávesou ESC nyní přepínáte mezi editorem zdrojového textu a
příkazovou řádkou. Zkuste si napsat první program
MOVE.L #$12345678,D0
RTS
Pozor, na začátku řádku stiskněte tabulátor aby se vynechalo místo. Na první
místo v řádku se totiž nepíše instrukce, ale tzv. návěstí, které zatím
nepotřebujeme. Mezi "MOVE.L" a operandy udělejte také tabulátor (místo mezer),
zdrojový text se vám bude lépe rovnat. Pokud jste tento vás první "program"
dopsali, zkuste si ho přeložit a spustit. Tedy: stiskněte ESC, jste v příkazové
řádce. Napište A, kód se přeloží s hláškami Pass 1, Pass 2, No Errors. Program
spustíte příkazem J. Co vlastně program dělá? První řádka plní registr D0 číslem
$12345678 (v hexadecimálním tvaru). Instrukce RTS pak znamená ukončení programu,
neboli návrat do assembleru. Pokud se vám všechno povedlo a program jste
spustili, objeví se vám stav registrů po ukončení programu (D0 by měl mít
hodnotu $123456789) a můžeme pokračovat. Všechny instrukce na MOTOROLE jsou
vymyšleny tak, aby šly provést vždy s jakýmkoliv registrem, tedy co de s D0, de
i s D6 atd. Jediný rozdíl je mezi adresovými a datovými registry, některé
instrukce se vztahují pouze na adresové, některé pouze na datové, což předurčuje
jejich použití. Příště si některé základní instrukce ukážeme, vysvětlíme, co
všechno se pomocí nich dá dělat a začneme používat systémové funkce. Do té doby
pečlivě studujte šestnáctkovou a dvojkovou soustavu, zkuste si mezi nimi převody
- v assembleru v příkazové řádce můžete napsat otazník a číslo (nebo matematický
výraz), a výsledek se vám zobrazí ve všech třech soustavách a navíc ještě čtyři
znaky. Zkuste sami přijít na to, co tyto znaky (jsou v uvozovkách) znamenají,
naučte se správně ovládat editor assembleru, nastavení preferencí a trace mód.
Trace mód se aktivuje klávesami Amiga+shift+D, a to rovnou z editoru. Daný
program se přeloží, můžete si ho krokovat a sledovat, jak se v průběhu programu
mění registry. Takže pečlivě studujte, příště začínáme naostro! Kromě věcí již
slíbených se dále naučíme co jsou příznaky, návěstí, relativní a absolutní
adresování, a spoustu jiných užitečných věcí. Nashledanou u příštího dílu ! Vytlačiť článok
Pozn.: články boli naskenované ako text a preto obsahujú aj zopár chýb. Taktiež neručíme za zdrojové kódy (Asm, C, Arexx, AmigaGuide, Html) a odkazy na web. Dúfame, že napriek tomu vám táto databáza dobre poslúži.
Žiadna časť nesmie byť reprodukovaná alebo inak šírená bez písomného povolenia vydavatela © ATLANTIDA Publishing
none
|