clanky/KaP

Kanály a proudy


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:

  • Kanál "P" PRINTER - komunikace s tiskárnou
  • Kanál "S" SCREEN - komunikace s horní částí obrazovky (uživatelské okno)
  • Kanál "K" KEYBOARD - slouží k vyslání nebo příjmu informace (např. INPUT, k době vkládání příkazů přímo z klávesnice atd.), využívá se dolní část obrazovky (systémové okno)
  • Kanál "R" WORKSPACE - není přístupný z BASICu, slouží ke skladování informací, které pak mohou být přečteny najednou.

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ů.

ADRESA HODNOTA BAJTU
 HEXDEC
23734F4244 \
      3509   9 / 2548
      36A9168 \
      3710  16 / 4264
      384B  75 kanal K
      39F4244 \
2374009   9 / 2548
      41C4196 \
      4215  21 / 5572
      4353  83 kanal S
      4481129 \
      450F   15 / 3969
      46C4196 \
      4715  21 / 5572
      4852  82 kanal R
      49F4244 \
2375009   9 / 2548
      51C4196 \
      5215  21 / 5572
      5350  80 kanal P
2375480  128 konec
Obr.1 Tabulka "Chanel Information"
 

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



     psp-ikona.gif, 2 kB    Text to HTML converter and formatter  builder_ikonka.gif, 3 kB
           
  Best Old Games      kabelmanie.gif, 2 kB  root_ico.gif, 2 kB  český diskmag pro počítače ZX Spectrum a kompatibilní
synapse.gif, 4 kB   TuningPC.cz - Vše pro tuning a casemodding vašeho PC        pspad88x31.gif  delphix.gif, 1 kB
sgatlantis_88x31_3.jpg, 4 kB  atlan.gif, 22 kB  arkon.jpg, 12 kB  ico_abeceda.gif, 888B  blog.idnes.cz   
           
       
 
  torry_logo.gif, 4 kB  

Stránka načtena za 0.00203 sekund.