Kanály a proudy mohou být používány jak BASICem, tak programy ve strojním kódu. V BASICových programech nelze ovšem využít všech možností, které mohou kanály uživateli poskytnout, i když i v BASICu je možné docílit některých zajímavých výsledků.
Myšlenka na níž je postavena existence kanálů je velmi jednoduchá: maximálně unifikovat způsob předávání informací takovým periferiím jako je tiskárna, mikrodrajv, disk, sp. - všechny tyto informace lze vyslat pomocí jediného příkazu a tím je PRINT.
Kanál vlastně představujje přenosovou linku spojující počítač s některým těchto zařízení. Chceme-li například předat informaci tiskárně, pak je nutné použít PRINT, ale použít k tomu odpovídající "linku" - kanál sloužící ke komunikaci s tiskárnou.
Normálně ve Spectru existují čtyři kanály:
Z úrovně BASICu lze využít pouze první tři z uvedených kamálů; nepoužíváme jejicj název, ale musíme použít číslo kanálu. Toto číslo je tzv. proud. Přiřazení kanálů a proudů je následující:
Proud | -3, 0, 1 | Kanál | K |
-2,2 | S | ||
3 | P | ||
-1 | R |
Proudy 4 až 15 jsou po startu systému uzavřeny, tj. není jim přiřazen žádný kanál.
Všechny proudy se záporným číslem jsou z BASICu nepřístupné, ovšem k využívání kanálů K, S, P stačí proudy 0, 1, 2 a 3.
Příkaz PRINT tiskne v kanále S (proud 2), LPRINT, který tiskne na tiskárně, se od PRINT liší pouze tím, že používá kanál P (přes proud 3). Chceme-li uvnitř příkazu PRINT nebo LPRINT změnit kanál tisku, pak je nutné použít znak # (hash), za kterým následuje číslo námi zvoleného proudu. Napíšeme-li:
PRINT #3; "text"
Pak je výsledek stejný jako LPRINT "text". Slovo se objedví na tiskárně. Kanál tisku lze měnit libovolně několikrát uvnitř jediného příkazu:
LPRINT "tisknu na tiskarne";#2;" ted v horni casti obrazovky";#0;"a nakonec v systemovm okne": PAUSE 0
Příkaz PAUSE 0 je použit proto, aby nápis v dolní části obrazovky nebyl okamžitě vymazán zprávou "0 O.K." .
Existuje teoretická možnost volby kanálu v instrukci INPUT, ale výběr je omezen na dva proudy: 0 a 1, tedy jen do kanálu K. V ostatních kanálech nelze INPUT použít, protože pouze kanál K může sloužit jako vstupní. Vstup z klávesnice je odesílán do dolní části obrazovky.
Kromě PRINT #, INPUT # a LIST # existují ještě příkazy umožňující otevírat nebo zavírat proudy, které může uživatel používat (proudy 4 až 15). Je to příkaz OPEN #, který proud otevírá a CLOSE #, který jej uzavře.
OPEN # číslo_kanálu, jméno_kanálu otevírá proud uvedeného čísla a přiřazuje mu kanál uvedeného názvu. Název je jednoznakový řetězec "K", "S" nebo "P" (velikost znaků nerozhoduje). Může být samozřejmě použita i řetězová proměnná o délce 1 a obsahující platný znak (jinak zpráva "Invalid file name"). Chceme-li tedy například otevřít proud 4 pro kanál K, napíšeme:
OPEN #4, "K" nebo OPEN #4,"k"
a od toho okamžiku PRINT #4; ... tiskne v dolní části obrazovky. Děje se tak do okamžiku, kdy kanál uzavřeme pomocí CLOSE #4. Pak pokus o použití tohoto proudu vede k protestu počítače: "Invalid stream". Při zavírání kanálů je třeba myslet, protože díky chybě v ROM vede pokus o zavření kanálu, který už byl zavřen, nebo nebyl vůbec otevřen, k havárii systému.
V programech, které vůbec nepoužívají strojový kód moho být kanály použity k tisku nějakých dat (např. jako v následujícím příkladě tabulky a b$) - podle potřeby na obrazovce nebo na tiskárně:
10 DIM a(20): DIM b$(20,16) ... 100 OPEN #4, "S" : GOSUB 1000 110 OPEN #4, "P" : GOSUB 1000 ... 1000 REM program tisknouci pole a() a b$() 1010 PRINT #4:" Pole a","Pole b$" 1020 FOR n=1 TO 20 1030 PRINT #4;n; TAB 3;a(n),b$(n) 1040 NEXT n 1050 RETURN
A to je prakticky vše, k čemu je možné využít kanály na úrovni BASICu. Jejich dokonalejší využití je možné až při použití assembleru a podprogramů uložených v ROM. Neznamená to, že se v BASICu nedá už nic podnikat - podprogramy obsluhy kanálů napsané v assembleru můžeme vložit do příkazů DATA, nebo jej natáhnout z pásku pomocí LOAD "" CODE. Provedením několika příkazů POKE "připojujících" náš podprogram k existující kanálům, získáme možnost tento podprogram používat příkazy PRINT, LIST nebo INPUT. O tom si povíme později.
Ve strojovém kódu je tisk poněkud komplikovanější, protože ve strojovém kódu není příkaz, který by byl ekvivalentní příkazu PRINT. Běží-li BASICový program a interpreter narazí na PRINT je provedena celá řada strojových podprogramů. První z těchto podprogramů je CHAN-OPEN sídlící v ROM na adrese 5633 (#1601), který otevírá kanál pro tisk. Otevření zde nemá stejný význam jako v BASICu - tam šlo o přiřazení proudu ke kanálu - zde jde pouze o nalezení a zapamatování si čísla daného kanálu. Před voláním tohoto podprogramu je v akumulátoru umístěno číslo otevíraného kanálu. Hodnota je zapsána v kódu W2 (dvojkový doplněk).
Je-li kanál otevřen, můžeme se věnovat vlastnímu tisku. Základní podprogram vysílající jediný bajt informace v používaném kanále je v ROM na adrese 16 (#10). Podprogram můžeme zavolat pomocí CALL 16 (CALL #10), nebo ještě jednodušeji RST 16 (RST #10). Tento podprogram vyšle na otevřený kanál znak, jehož kód nalezne v akumulátoru. Takže chceme-li např. v horní části obrazovka vytisknout písmeno "A" můžeme napsat následující program: (nemáme-li v počítači natažený assembler, použijte program, který je uveden dále.)
3E FE LD A,-2 ; číslo kanálu CD 01 16 CALL 5633 ; otevření kanálu S 3E 41 LD A,65 ; kód znaku "A" C9 RET ; návrat
Nejdříve otevřeme kanál přiřazený proudu 2 - tedy S, pak do něj pošleme kód znaku "A". Chceme-li nyní v kanále S vytisknout další znak, pak nemusíme kanál znovu otevírat. Každý kanál zůstává otevřen do okamžiku, kdy se otevře jiný kanál.
Chceme-li vytisknout delší text, pak není příliž pohodlné vysílat každý znak separátně. V ROM je naštěstí uloženo několik podprogramů, které tento problém řeší. První je na adrese 8252 (#303 PR-STRING). Tiskne text, jehož délka je uložena v registrovém páru BC a adresa prvního znaku v registrovém páru DE. Text může obsahovat libovolné znaky o kódech 0 - 255. Podprogram může pracovat v libovolné kanále, je třeba jen nezapomenout před jeho použitím otevřít požadovaný kanál.
3E 02 LD A,2 ; číslo proudu CD 01 16 CALL 5633 ; otevření kanálu S 11 72 09 LD DE,2466 ; adresa řetězce 01 1E 00 LD BC,30 ; délka CD 3C 20 CALL 8252 ; tisk textu C9 RET ; návrat
Druhá procedura tisknoucí texty je na adrese 3082 (#0C0A PO-MSG). To tiskne pouze řetězce znaků s kódy 0 - 127, ale má to tu výhodu, že můžeme mít v paměti uloženo za sebou až 256 řetězců a nestarat se ani o adresu ani o délku kteréhokoliv z nich.
V bajtu těsně před prvním řetězcem uložíme hodnotu větší než 127 a za ní text řetězce. Jeho konec označíme tak, že ke kódu posledního znaku přičteme 128 (nastavíme bit 7 na 1, číslo je v konvenci dvojkového dopňku záporné). Hned za tímto bajtem může být začátek dalšího řetězce, zapsaného tímtéž způsobem. Chceme-li nyní některý z těchto řetězců vytisknout, vložíme do DE adresu bajtu, který je před prvním znakem prvního řetězce, do aumulátoru vložíme pořadové číslo textu, který se má tisknout. Je to hodnota osmibitová, tedy 0 - 255, kde 0 označuje první řetězec, 1 druhý ... 255 dvěstěpadesátýšestý. V ROMce byste našli několik oblastí textu uloženého tímto způsobem. Vyzkoušejte si jeden z nich - jsou v něm uloženy texty všech chybových zpráv:
3E 02 LD A,2 ; číslo proudu CD 01 16 CALL 5633 ; otevření kanálu S AF XOR A ; znulování registru A LOOP F5 PUSH AF ; uschování stavu A 11 91 13 LD DE,5009 ; adresa bajtu před prvním textem 0D 0A 0C CALL 3082 ; tisk textu o čísle A 3E DD LD A,13 ; přechod na nový řádek D7 RST 16 ; tisk(CR) F1 POP AF ; obnovení obsahu A 3C INC A ; další text FE 1E CP 30 ; návrat, byl-li již D0 RET NC ; třicátý bajt 18 EF JR LOOP ; (-17) opakuj
Proanalyzujte činnost tohoto programu a porovnejte vytisklé zprávy se skutečným obsahem oblasti paměti 5009 - 5460 (pomocí PEEK ... a CHR$ PEEK ...).
Pokud je v A hodnota 0 až 9, můžete ji vytisknout pomocí CALL 5615 - je to totéž jako ADD A, (kód znaku "0") přes RST 16. Chcete-li vytisknout hodnotu větší než jednocifernou ale menší než 10000, můžete ji uložit do BC a provést podprogram na adrese 6683 (#1A1B OUT-NUM-1).
Pokud nám nestačí ani tento rozsah, pak musíte použít subrutiny tzv. "kalkulátoru". Je to část interpreteru BASICu, která se zabívá všemi druhy výpočtů a k ukládání hodnot požívá oblast paměti označovanou jako "CALCULATOR STACK" - zásobník kalkulátoru. Pomocí podprogramů kalkulátoru je možné hodnoty uložené v zásobníku kalkulátoru sčítat, odčítat, násobit, dělit, umocňovat, používat je jako argumenty různých funkcí atd. Je také možné vytisknout hodnotu čísla, které se nachází na vršku zásobníku. Stačí použít pouze dva podprogramy: první - který zapíše hodnotu z registrů mikroprocesoru na vršek zásobníku a druhý, který tuto hodnotu vytiskne.
Abychom zapsali hodnotu na zásobník, uložíme ji do páru BC a zavoláme podprogram na adrese 11563 (#2D28 STACK-BC). Pak otevřeme příslušný kanál a vytiskneme hodnotu zapsanou na zásobník pomocí CALL 11747 (#2DE3 PRINT-FP).
01 39 30 LD BC,12345 ; zápis hodnoty CD 2B 2D CALL 11563 ; 12345 na zásobník kalkulátoru 3E 02 LD A,2 ; číslo proudu CD 01 16 CALL 5633 ; otevření kanálu S CD E3 2D CALL 11747 ; tisk hodnoty z vršku zásobníku C9 RET ; návrat
Tyto podprogramy umožňují vytištění prakticky libovolného textu nebo hodnoty a lze je s výhodou používat programy napsanými v assembleru. Na úrovni strojového kódu v podstatě odpovídající příkazu PRINT. Umožňují využívat kanály a jejich studiem se naučíte využívat kanály ke speciálním účelům - např. k vylepšení příkazu PRINT, k zabezpečení programů před vylistováním atp. Následuje výpis jednoduchého programu, který vám umožní spustit mc rutiny, které jsme probrali:
1 REM vyzkouseni prikladu v assembleru 10 Clear 59999: LET x=60000 20 READ a,b,c,d,e,f 30 DATA 10,11,12,13,14,15 40 READ a$ 50 FOR n=1 TO LEN a$ STEP 2 60 POKE x,VAL a$(n)*16+VAL a$(n+1) 65 LET x=x+1 70 NEXT n 80 RANDOMIZE USR 60000 85 REM umistete sestnactkovy zapis mc programu v radku 90 DATA Např. náš první příklad by vypadal následovně: 90 DATA "3EFECD01163E41D7C9"
Probereme si system kanů Spectra a pokusíme se proniknout do tajemství jejich činnosti. Základní instrukci vysílající znaky otevřeným kanálem je RST 16 (RST #10). Využívá ji většina rutin v ROM. Např. rutina na adrese 8252 (#203C) s názvem PR-STRING postupně umísťuje do akumulátoru znaky tištěného řetězce a posílá je přes RST 16.
Jak to, že RST 16 tiskne jednou v kanále S a jindy v kanále K? V čem spočívá otevření kanálu?
V oblasti rezervované pro operační systém Spectra existuje několik oblastí sloužících k obsluze kanalů. K dispozici jsou také určité systémové proměnné a oblast CHANEL INFORMATION, ležící mezi systémovými proměnnými a BASICem, obvykle na adrese 23734. Pro ujištění, zda tam skutečně je stačí zjistit hodnotu sstémové proměnné CHANS, v níž je uložena adresa počátku této oblasti.
Zde jsou uloženy adresy rutin obsluhy kanálů. Pro informace pro jednotlový kanál je určeno 5 bajtů.
|
První dva bajty obsahují adresu rutiny obsluhy kanálu v případě, že je používán jako výstupní (OUTPUT), dba následující pro adresu rutiny obsluhující kanál jako vstupní (INPUT). Poslední pátý bajt je kód jednopísmenného názvu kanálu. Pro kanály S, P a R, které jsou pouze výstupními kanály (nemohou být použity pro příjem informací od vnějších zařízení), ukazuje druhá adresa na rutinu generující zprávu "Invalid I/O device".
Za informacemi o všech existujících kanálech se nachází koncový znak - bajt s hodnotou 128 (#80), oddělující CHANNEL INFORMATION od následujícího programu v BASICu.
V době otevření kanálu jsou používány systémové proměnné STRMS a CURCHL. Proměnná STRMS je na adrese 23568 a má délku 38 bajtů. Obsahuje informace o přiřazení kanálu proudům, tj. informaci o tom, že kanál K můžeme používat přes proudy -3, 0 a 1 a kanál P pouze přes proud 3. Viz obr2. Pro každý proud jsou určeny dva bajty používané rutinou otevírajícíkanály (CHAN-OPEN na adrese 5633 (#1601)) jako jedna dvoubajtová hodnota. Je-li rovná 0, pak to znamená, že proud je uzavřen (není mu přiřazen žádný kanál). Pokus otevřít tento kanál skončí zprávou "Invalid stream". Je-li zde hodnota různá od nuly, pak je použita jako offset pro adresu otevíraného kanálu v CHANNEL INFORMATION.
Stránka byla už zobrazena: 156 ×
Aktualizováno: 14. 12. 2022, 09:04
Stránka načtena za 0.00203 sekund.