Powrót do spisu treści

Rozdział 2

CENTRALNA PROCEDURA I/O

    Centralna procedura wejścia/wyjścia (CIO) umożliwia komunikację ze wszystkimi urządzeniami zewnętrznymi, które są przyłączone do systemu komputerowego. Jest ona dostępna bezpośrednio z poziomu języka maszynowego oraz z poziomu języków programowania poprzez instrukcje wejścia/wyjścia (np. w Atari Basic: OPEN, CLOSE, PRINT, GET itd.). Przez urządzenia zewnętrzne należy rozumieć wszystkie urządzenia do komunikacji komputera z otoczeniem w tym również klawiaturę, która fizycznie jest wbudowana do komputera. Dodatkowym, oddzielnym urządzeniem zewnętrznym Atari jest tzw. edytor, który stanowi połączenie klawiatury (wejście) i ekranu w trybie 0 (wyjście).

    Przed wywołaniem procedury CIO program użytkownika musi umieścić w odpowiednim IOCB kod operacji do wykonania oraz parametry potrzebne dla żądanej operacji (np. adres bufora danych). Ponadto numer wybranego IOCB pomnożony przez 16 umieszczany jest w rejestrze indeksowym X procesora.

2.1. Główna procedura CIO

    Zadaniem głównej procedury CIO jest sprawdzenie poprawności podanego kodu operacji i numeru IOCB. Następnie według odczytanego kodu wywoływana jest podrzędna procedura CIO wykonująca żądaną operację.
        < CIOMAIN >
             |
             v
         /--------\
        / poprawny \ nie    +-------+
       <   numer    >------>| Y=$86 |
        \  IOCB ?  /        +-------+
         \--------/             |
             | tak              v
             v             +--------+
     +---------------+     | CIORET |
     |  przepisanie  |     +--------+
     | IOCB do ZIOCB |
     +---------------+
             |
             |
             v
        /----------\ tak           /---------\ tak
       < ICHIDZ=$7F >---->--------< ICCOM=$0C >----------+
        \----------/               \---------/           |
             | nie                      | nie            |
             v                          v                |
             +<---------------+    /--------\ tak        |
             |                |   < HNDLOD=0 >--->-+     |
             v                |    \--------/      |     |
         +-------+            |     nie |          |     |
         | Y=$84 |            |         v          v     |
         +-------+            |   ++--------++ +-------+ |
             |                |   || PRPLNK || | Y=$82 | |
             v                |   ++--------++ +-------+ |
        /---------\ tak       |         |          |     |
       < ICCOM<$03 >---->-+   |         v          |     |
        \---------/       |   |  nie /------\      |     |
             |            |   +-<---< błąd ? >     |     |
             v            |          \------/      |     |
   +-------------------+  |             | tak      |     |
   |  odczyt  indeksu  |  |             v          |     |
   | adresu sterownika |  |        ++--------++    |     |
   +-------------------+  +------->|| CIORET ||<---+     |
             |                     ++--------++          |
             v                                           |
        /--------\ tak     ++--------++                  |
       < indeks=0 >------->||  OPEN  ||                  |
        \--------/         ++--------++                  |
         nie |                                           |
             v                                           |
        /--------\ tak     ++--------++                  |
       < indeks=2 >------->|| CLOSE  ||<-----------------+
        \--------/         ++--------++
         nie |
             v
        /---------\ tak    ++--------++
       < indeks>=8 >------>|| STATUS ||
        \---------/        ++--------++
         nie |
             v
        /--------\ tak     ++--------++
       < indeks=4 >------->||  READ  ||
        \--------/         ++--------++
         nie |
             v
        ++-------++
        || WRITE ||
        ++-------++

       Rys.3. Struktura głównej procedury CIO.
    Na początku procedury zawartości rejestru X i akumulatora są zapisywane w pomocniczych rejestrach ICAX5Z i ICAX6Z. Następnie sprawdzane jest, czy numer IOCB jest pełną wielokrotnością liczby 16 i czy jest mniejszy od $80. Negatywny wynik powoduje umieszczenie w rejestrze Y wartości $86 (kod błędu BAD IOCB NUMBER - błędny numer IOCB) i przejście do procedury CIORET kończącej operację CIO.
            0100 ;CIO MAIN routine
            0110 ;
            0120 CIOCLS = $E57C
            0130 CIOOPN = $E53F
            0140 CIOREAD = $E5B2
            0150 CIORET = $E670
            0160 CIOSTSP = $E597
            0170 CIOWRT = $E61E
            0180 COMTAB = $E72D
            0190 HNDLOD = $02E9
            0200 ICAX5Z = $2E
            0210 ICAX6Z = $2F
            0220 ICCHID = $0340
            0230 ICCOMT = $17
            0240 ICCOMZ = $22
            0250 ICHIDZ = $20
            0260 PRPLNK = $CA29
            0270 ;
            0280     *=  $E4DF
            0290 ;
            0300     STA ICAX6Z
            0310     STX ICAX5Z
            0320     TXA
            0330     AND #$0F
            0340     BNE BNAM
            0350     CPX #$80
            0360     BCC MOVE
            0370 BNAM LDY #$86
            0380     JMP CIORET
            0390 MOVE LDY #$00
            0400 NEXT LDA ICCHID,X
            0410     STA ICHIDZ,Y
            0420     INX
            0430     INY
            0440     CPY #$0C
            0450     BCC NEXT
            0460     LDA ICHIDZ
            0470     CMP #$7F
            0480     BNE PCMD
            0490     LDA ICCOMZ
            0500     CMP #$0C
            0510     BEQ CIOCLS
            0520     LDA HNDLOD
            0530     BNE LDH
            0540 ;NonEXistent Device ERror
            0550 NEXDER LDY #$82
            0560 EXIT JMP CIORET
            0570 LDH JSR PRPLNK
            0580     BMI EXIT
            0590 PCMD LDY #$84
            0600     LDA ICCOMZ
            0610     CMP #$03
            0620     BCC EXIT
            0630     TAY
            0640     CPY #$0E
            0650     BCC CMD
            0660     LDY #$0E
            0670 CMD STY ICCOMT
            0680     LDA COMTAB-3,Y
            0690     BEQ CIOOPN
            0700     CMP #$02
            0710     BEQ CIOCLS
            0720     CMP #$08
            0730     BCS CIOSTSP
            0740     CMP #$04
            0750     BEQ CIOREAD
            0760     JMP CIOWRT
    Jeżeli numer IOCB jest poprawny, to jego zawartość jest przepisywana na stronę zerową do ZIOCB. Nie ją jedynie przenoszone dwa ostatnie bajty IOCB, gdyż w odpowiadających im rejestrach ZIOCB przechowywane są już wartości z akumulatora i rejestru X.

    W następnej kolejności sprawdzany jest indeks wpisu w tabeli HATABS - ICHIDZ (IOCB CHannel IDentification). Jego wartość równa $7F oznacza, że operacja dotyczy "nowego urządzenia". W takim przypadku, jeśli kod operacji jest równy $0C (CLOSE), następuje skok do procedury CIOCLS. W przeciwnym razie kontrolowany jest znacznik HNDLOD. Gdy jest on równy zero, to do rejestru Y wpisywana jest wartość $82 (NON EXISTENT DEVICE - urządzenie nie istnieje) i procedura CIOMAIN kończy się skokiem do CIORET. Po stwierdzeniu obecności urządzenia wywoływana jest procedura PRPLNK, która obsługuje nowe urządzenia (zob. rozdział 6.2.).

    Wartość ICHIDZ różna od $7F oznacza, że komunikacja z urządzeniem będzie wykonywana przez standardowe procedury CIO. Teraz do rejestru Y wpisywany jest kod błędu INVALID COMMAND ($84 - błędny rozkaz) i sprawdzana jest zawartość rejestru ICCOMZ. Gdy jest ona mniejsza od $03, następuje skok do CIORET. Poprawny kod operacji powoduje (po zapisaniu go do rejestru ICCOMT) pobranie z tabeli COMTAB wartości indeksu wskazującego położenie adresu procedury wykonującej tą operację w tabeli adresowej sterowników. Bliższe informacje na ten temat są zawarte w rozdziale 2.2.
            0100 ;COMmand TABle
            0110 ;
            0120     *=  $E72D
            0130 ;
            0140     .BYTE $00,$04,$04,$04
            0150     .BYTE $04,$06,$06,$06
            0160     .BYTE $06,$02,$08,$0A 
    Teraz przeprowadzane jest rozpoznanie operacji do wykonania poprzez sprawdzanie wartości odczytanego indeksu. Wartość zero oznacza operację otwarcia kanału IOCB (OPEN) i powoduje przejście do procedury CIOOPN. Wartość dwa oznacza zamknięcie kanału (CLOSE) - wywołuje skok do CIOCLS. Indeks większy od $07 oznacza operację odczytu statusu (STATUS) lub operację specjalną (SPECIAL), specyficzną dla danego urządzenia. W tym przypadku wykonywany jest skok do CIOSTSP. Na końcu sprawdzany jest indeks operacji odczytu ($04 - READ) - skok do CIOREAD. Jeśli żadna z wyżej wymienionych operacji nie została rozpoznana, to znaczy, że chodzi o zapis (WRITE) i następuje skok do CIOWRT.

2.1.1. Zakończenie procedury CIO

    Zarówno główna, jak i wszystkie szczegółowe procedury CIO kończą się skokiem do procedury CIORET. Ma ona dwa punkty początkowe: CIORET i CPLCIO. Rozpoczęcie procedury od etykiety CIORET powoduje zapisanie aktualnej zawartości rejestru Y procesora do rejestru statusu ZIOCB (ICSTZ - IOCB STatus, Zeropage). Operacja ta jest omijana przy rozpoczęciu od etykiety CPLCIO.
            0100 ;CIO RETurn routine
            0110 ;
            0120 HNDLOD = $02E9
            0130 ICAX5Z = $2E
            0140 ICAX6Z = $2F
            0150 ICBAZ = $24
            0160 ICBUFA = $0344
            0170 ICCHID = $0340
            0180 ICHIDZ = $20
            0190 ICSTZ = $23
            0200 ;
            0210     *=  $E670
            0220 ;
            0230     STY ICSTZ
            0240 ;ComPLete CIO operation
            0250 CPLCIO LDY ICAX5Z
            0260     LDA ICBUFA,Y
            0270     STA ICBAZ
            0280     LDA ICBUFA+1,Y
            0290     STA ICBAZ+1
            0300     LDX #$00
            0310     STX HNDLOD
            0320 NEXT LDA ICHIDZ,X
            0330     STA ICCHID,Y
            0340     INX
            0350     INY
            0360     CPX #$0C
            0370     BCC NEXT
            0380     LDA ICAX6Z
            0390     LDX ICAX5Z
            0400     LDY ICSTZ
            0410     RTS
    Zadaniem CIORET jest przekazanie zawartości ZIOCB do odpowiedniego IOCB. W tym celu najpierw z rejestru ICAX5Z jest pobierany numer właściwego IOCB. Następnie adres bufora w ZIOCB jest odtwarzany według zawartości IOCB i zerowany jest rejestr HNDLOD. Teraz kolejno zawartości rejestrów ZIOCB są przenoszone do IOCB (oprócz dwóch ostatnich bajtów).

    Na początku procedury CIOMAIN w rejestrach ICAX5Z i ICAX6Z zostały zapamiętane zawartości rejestru X i akumulatora. Przed zakończeniem CIO są one odtwarzane i dodatkowo do rejestru Y pobierany jest status wykonanej operacji I/O. Ponieważ jest to ostatnie polecenie przed końcem procedury, to w przypadku błędu (status większy od $7F) po powrocie do miejsca wywołania CIO bit N (negative) w rejestrze statusu procesora jest ustawiony. Pozwala to na bardzo proste wykrycie błędu i przejście do dalszej części programu (np. procedury obsługi błędu) przy użyciu rozkazów BPL (Branch if PLus) lub BMI (Branch if MInus).

2.2. Tabele adresowe sterowników

    Kilkakrotnie już wspominane były tabele adresów procedur obsługi urządzeń zewnętrznych. Według umieszczonych w nich adresów CIO rozpoznaje procedury dotyczące poszczególnych urządzeń. W systemie operacyjnym Atari występują dwa rodzaje tabel adresowych: HATABS i tabele wektorów sterowników (procedur obsługi).

    Tabela HATABS (Handler Address TABleS) znajduje się na trzeciej stronie pamięci i zawiera nazwy wszystkich urządzeń i adresy ich tabel wektorów. Każdy wpis w tabeli HATABS składa się z trzech bajtów: nazwa urządzenia, młodszy bajt adresu i starszy bajt adresu:
                     +-------------------+  -+
            1 bajt   | nazwa urządzenia  |   |
                     +-------------------+   |
            2 bajt   | LSB adresu tabeli |   +- jeden wpis
                     +-------------------+   |
            3 bajt   | MSB adresu tabeli |   |
                     +-------------------+  -+
                     |                   |
                     |   dalsze  wpisy   |
                     |                   |
                     +-------------------+

               Rys.4. Struktura tabeli HATABS
    Nazwa urządzenia w HATABS jest zapisaną w kodzie ASCII pierwszą literą nazwy symbolicznej, np. Cassette, Editor, Keyboard, Printer itd. Są to te same nazwy, które występują w Atari Basic w instrukcji OPEN. Początkowo tabela HATABS zawiera pięć wpisów urządzeń (P, C, E, S i K) przeniesionych tu z tabeli INIT31A podczas inicjowania systemu:
            0100 ;Handler Address TABleS
            0110 ;
            0120 CASVEC = $E440
            0130 EDTVEC = $E400
            0140 KBDVEC = $E420
            0150 PRTVEC = $E430
            0160 SCRVEC = $E410
            0170 ;
            0180     *=  $031A
            0190 ;
            0200     .BYTE 'P
            0210     .WORD PRTVEC
            0220     .BYTE 'C
            0230     .WORD CASVEC
            0240     .BYTE 'E
            0250     .WORD EDTVEC
            0260     .BYTE 'S
            0270     .WORD SCRVEC
            0280     .BYTE 'K
            0290     .WORD KBDVEC
    Dalsze miejsca w HATABS są przeznaczone do zainstalowania innych urządzeń zewnętrznych. Wszystkie niewykorzystywane wpisy mają wartość zero. Razem z wpisami już istniejącymi w tabeli HATABS można umieścić 11 różnych urządzeń zewnętrznych.

    Dwa bajty adresowe wpisu w HATABS wskazują na tabelę adresów procedur obsługi poszczególnych operacji wykonywanych przez urządzenie. Należy zwrócić uwagę, że wszystkie adresy są zmniejszone o jeden. Ostatnie cztery bajty zawierają rozkaz skoku do procedury inicjowania oraz bajt zerowy.
                     +-----------+
              +$00   |   OPEN-1  |
                     +-----------+
              +$02   |  CLOSE-1  |
                     +-----------+
              +$04   |   GET-1   |
                     +-----------+
              +$06   |   PUT-1   |
                     +-----------+
              +$08   | STATUS-1  |
                     +-----------+
              +$0A   | SPECIAL-1 |
                     +-----------+
              +$0C   | JMP  INIT |
                     +-----------+
              +$0F   |    $00    |
                     +-----------+

        Rys.5. Tabela adresowa sterownika
    Urządzenia zainstalowane na stałe posiadają tabele adresów zapisaną w pamięci ROM. Można jednak napisać dla nich własne procedury obsługi i po umieszczeniu w dowolnym miejscu RAM tabeli adresów zmienić wektor w HATABS tak, aby wskazywał na nową tabelę adresową. Standardowa tabela zapisana w ROM-ie jest następująca:
            0100 ;DEVice HAndler Table
            0110 ;
            0120 CASCLS = $FDCF
            0130 CASINIT = $FCDB
            0140 CASOPN = $FCE6
            0150 CASRDBT = $FD7A
            0160 CASSP = $FCE5
            0170 CASST = $FDCC
            0180 CASWRT = $FDB4
            0190 DRAW =  $F9AF
            0200 EDOPN = $EF94
            0210 EDSP =  $F22D
            0220 EGETCH = $F24A
            0230 EOUTCH = $F2B0
            0240 GETCH = $F180
            0250 KBGBYT = $F2FD
            0260 KBOPN = $F21E
            0270 OUTCH = $F1A4
            0280 POWERON = $EF6E
            0290 PRCLS = $FF07
            0300 PRINIT = $FE99
            0310 PROPN = $FEC2
            0320 PRRDSP = $FEC1
            0330 PRSTAT = $FEA3
            0340 PRWRT = $FECB
            0350 SCOPN = $EF8E
            0360 SCRFIN = $F22E
            0370 ;
            0380     *=  $E400
            0390 ;
            0400 EDTVEC .WORD EDOPN-1
            0410     .WORD SCRFIN-1
            0420     .WORD EGETCH-1
            0430     .WORD EOUTCH-1
            0440     .WORD KBOPN-1
            0450     .WORD EDSP-1
            0460     JMP POWERON
            0470     .BYTE $00
            0480 SCRVEC .WORD SCOPN-1
            0490     .WORD SCRFIN-1
            0500     .WORD GETCH-1
            0510     .WORD OUTCH-1
            0520     .WORD KBOPN-1
            0530     .WORD DRAW-1
            0540     JMP POWERON
            0550     .BYTE $00
            0560 KBDVEC .WORD KBOPN-1
            0570     .WORD KBOPN-1
            0580     .WORD KBGBYT-1
            0590     .WORD EDSP-1
            0600     .WORD KBOPN-1
            0610     .WORD EDSP-1
            0620     JMP POWERON
            0630     .BYTE $00
            0640 PRTVEC .WORD PROPN-1
            0650     .WORD PRCLS-1
            0660     .WORD PRRDSP-1
            0670     .WORD PRWRT-1
            0680     .WORD PRSTAT-1
            0690     .WORD PRRDSP-1
            0700     JMP PRINIT
            0710     .BYTE $00
            0720 CASVEC .WORD CASOPN-1
            0730     .WORD CASCLS-1
            0740     .WORD CASDRBT-1
            0750     .WORD CASWRT-1
            0760     .WORD CASST-1
            0770     .WORD CASSP-1
            0780     JMP CASINIT
            0790     .BYTE $00
    Z tabeli tej pobierane są przez procedurę CIO adresy procedur obsługi poszczególnych operacji dla konkretnych urządzeń. Sposób wykorzystania tej tabeli przez procedury systemu operacyjnego jest opisany w następnych rozdziałach.

    Dodanie nowego urządzenia do tabeli HATABS nie wymaga nawet pisania specjalnej procedury. Do tego celu służy znajdująca się 2już w systemie operacyjnym procedura NEWDEV. Przed jej wywołaniem trzeba jedynie umieścić w rejestrze X nazwę urządzenia, a w rejestrze Y i w akumulatorze odpowiednio młodszy i starszy bajt adresu tabeli adresowej procedur obsługi.
            0100 ;NEW DEVice
            0110 ;
            0120 HATABS = $031A
            0130 ;
            0140     *=  $EEBC
            0150 ;
            0160     PHA
            0170     TYA
            0180     PHA
            0190     TXA
            0200     LDX #$00
            0210 NEXT1 CMP HATABS,X
            0220     BEQ FOUND
            0230     INX
            0240     INX
            0250     INX
            0260     CPX #$22
            0270     BMI NEXT1
            0280     LDX #$00
            0290     TAY
            0300     LDA #$00
            0310 NEXT2 CMP HATABS,X
            0320     BEQ EMPTY
            0330     INX
            0340     INX
            0350     INX
            0360     CPX #$22
            0370     BMI NEXT2
            0380     PLA
            0390     PLA
            0400     LDY #$FF
            0410     SEC
            0420     RTS
            0430 FOUND PLA
            0440     TAY
            0450     PLA
            0460     INX
            0470     SEC
            0480     RTS
            0490 EMPTY TYA
            0500     STA HATABS,X
            0510     PLA
            0520     STA HATABS+1,X
            0530     PLA
            0540     STA HATABS+2,X
            0550     CLC
            0560     RTS
    Na początku procedury zawartości akumulatora i rejestru X są umieszczane na stosie, a rejestr X (nazwa urządzenia) przepisywany jest do akumulatora. Następnie wykonywane są dwie pętle przeszukujące HATABS.

    Pierwsza pętla sprawdza, czy urządzenie o podanej nazwie znajduje się już w HATABS. Jeśli tak, to po odtworzeniu ze stosu zawartości rejestru Y i akumulatora procedura kończy się z ustawionym bitem Carry statusu procesora. Rejestr X zawiera wtedy indeks młodszego bajtu wektora w HATABS, co pozwala na bezpośrednią zmianę tego wektora poprzez sekwencję rozkazów STY HATABS,X, INX, STA HATABS,X.

    Gdy poszukiwane urządzenie nie zostało znalezione, wykonywana jest druga pętla. Jej zadaniem jest wykrycie pierwszego wolnego miejsca na wpis w HATABS. Jeżeli tabela HATABS jest całkowicie zapełniona, to ustawiany jest bit Carry, w rejestrze Y umieszczana jest wartość $FF i procedura się kończy.

    Po wykryciu wolnego miejsca w HATABS umieszczana jest w tabeli nazwa urządzenia, a następnie pobrany ze stosu adres tabeli jego procedur obsługi. W tym przypadku przed zakończeniem procedury bit Carry jest kasowany w celu wskazania pomyślnego przebiegu procedury.

2.2.1. Procedury korzystające z HATABS

    Z tabelami adresowymi sterowników jest związanych jeszcze kilka procedur pomocniczych wykorzystywanych przez procedury operacji CIO. Są to procedury DEVNUM, CMPENT i GOHAND oraz pośrednio procedura CIOJMP.

    Zadaniem procedury DEVNUM jest ustalenie numeru urządzenia, którego dotyczy operacja I/O; a w drugiej części rozpoczynającej się od etykiety DVSRCH - odnalezienie wpisu urządzenia w HATABS.
            0100 ;DEVice NUMber
            0110 ;
            0120 HATABS = $031A
            0130 ICBAZ = $24
            0140 ICHIDZ = $20
            0150 ICDNOZ = $21
            0160 ;
            0170     *=  $E6FF
            0180 ;
            0190     SEC
            0200     LDY #$01
            0210     LDA (ICBAZ),Y
            0220     SBC #'1
            0230     BMI SET0
            0240     CMP #$09
            0250     BCC STDN
            0260 SET0 LDA #$00
            0270 STDN STA ICDNOZ
            0280     INC ICDNOZ
            0290 ;DeVice SeaRCH
            0300 DVSRCH LDY #$00
            0310     LDA (ICBAZ),Y
            0320 ;Find DeVice HaNDler
            0330 FDVHND BEQ ERR
            0340     LDY #$21
            0350 NEXT CMP HATABS,Y
            0360     BEQ SUC
            0370     DEY
            0380     DEY
            0390     DEY
            0400     BPL NEXT
            0410 ERR LDY #$82
            0420     SEC
            0430     RTS
            0440 SUC TYA
            0450     STA ICHIDZ
            0460     CLC
            0470     RTS
    Procedura DEVNUM w celu ustalenia numeru urządzenia pobiera najpierw drugi bajt z bufora wskazywanego przez rejestr ICBAZ (bufor musi zawierać nazwę urządzenia). Następnie sprawdza, czy jego wartość mieści się w dozwolonym zakresie (dopuszczalne są numery urządzeń od 1 do 9). Poprawny numer urządzenia jest umieszczany w rejestrze ICDNOZ, a gdy jest nieprawidłowy, to do ICDNOZ wpisywane jest 1.

    Teraz odczytywany jest z bufora pierwszy bajt, który określa nazwę urządzenia i tabela HATABS jest przeszukiwana w celu odnalezienia wpisu tego urządzenia. Po napotkaniu wpisu jego indeks w HATABS jest umieszczany w rejestrze ICHIDZ i bit Carry jest kasowany. Gdy tabela nie zawiera poszukiwanego wpisu, to w rejestrze Y umieszczany jest kod błędu $82 (NON EXISTENT DEVICE) i bit Carry jest ustawiany.

    Warto przy tym zauważyć, że tabela HATABS jest przeszukiwana od końca. Jeżeli więc zostanie umieszczony w niej drugi wpis tego samego urządzenia (np. nowa procedura obsługi drukarki), to zostanie on odnaleziony wcześniej niż wpis oryginalny. Umożliwia to wprowadzenie nowego wpisu bez kasowania starego.

    Procedura CMPENT służy do ustalenia adresu początkowego procedury obsługi wykonującej żądaną operację I/O. Na początku odczytywany jest z rejestru ICHIDZ indeks urządzenia w HATABS. Jeśli jest on większy od $21, to w rejestrze Y umieszczany jest kod błędu $85 (IOCB NOT OPEN - IOCB nie otwarty) i po ustawieniu bitu Carry procedura się kończy.

    Jeśli wartość indeksu jest prawidłowa, to według niej wektor tabeli adresowej odczytywany jest z HATABS i umieszczany w rejestrach ICAX3Z oraz ICAX4Z. Następnie według kodu operacji pobranego z ICCOMT określany jest (przy pomocy tabeli COMTAB) indeks adresu procedury, która wykonuje żądaną operację. Znaleziony adres jest przepisywany z tabeli adresowej do rejestrów ICAX3Z i ICAX4Z. W celu zasygnalizowania poprawnego przebiegu procedury, przed jej zakończeniem kasowany jest jeszcze bit Carry.
            0100 ;CoMPute ENTry
            0110 ;
            0120 COMTAB = $E72D
            0130 HATABS = $031A
            0140 ICAX3Z = $2C
            0150 ICAX4Z = $2D
            0160 ICCOMT = $17
            0170 ICCOMZ = $22
            0180 ICHIDZ = $20
            0190 ;
            0200     *=  $E695
            0210 ;
            0220     LDY ICHIDZ
            0230     CPY #$22
            0240     BCC LAD
            0250     LDY #$85
            0260     BCS END
            0270 LAD LDA HATABS+1,Y
            0280     STA ICAX3Z
            0290     LDA HATABS+2,Y
            0300     STA ICAX4Z
            0310     LDY ICCOMT
            0320     LDA COMTAB+3,Y
            0330     TAY
            0340     LDA (ICAX3Z),Y
            0350     TAX
            0360     INY
            0370     LDA (ICAX3Z),Y
            0380     STA ICAX4Z
            0390     STX ICAX3Z
            0400     CLC
            0410 END RTS
    Wywołanie wybranej procedury obsługi urządzenia jest wykonywane przez procedurę GOHAND.
            0100 ;GO to HANDler
            0110 ;
            0120 CIOJMP = $E6F4
            0130 ICSTZ = $23
            0140 ;
            0150     *=  $E6EA
            0160 ;
            0170     LDY #$92
            0180     JSR CIOJMP
            0190     STY ICSTZ
            0200     CPY #$00
            0210     RTS
    Umieszcza ona najpierw w rejestrze Y kod błędu $92 (FUNCTION NOT IMPLEMENTED - operacja niedozwolona), a następnie poprzez procedurę CIOJMP wywołuje sterownik urządzenia zewnętrznego. Po zakończeniu operacji i powrocie do GOHAND zawartość rejestru Y jest przepisywana do ICSTZ, a poprzez rozkaz CPY bit Negative rejestru statusu otrzymuje wartość sygnalizującą powodzenie (lub nie) operacji. Umieszczenie w rejestrze Y kodu błędu $92 przed wywołaniem procedury obsługi żądanej operacji znakomicie upraszcza projektowanie procedur operacji niedozwolonych - wystarczy jako adres takiej operacji podać adres rozkazu RTS. Rozwiązanie to jest często stosowane w OS Atari oraz w sterownikach urządzeń instalowanych po zainicjowaniu systemu.

    Procedura CIOJMP służy wyłącznie do wykonania skoku do procedury obsługi urządzenia, której adres jest zawarty w rejestrach ICAX3Z i ICAX4Z. Bardzo interesujący jest natomiast sposób wykonania tego skoku.
            0100 ;CIO JuMP routine
            0110 ;
            0120 ICAX3Z = $2C	
            0130 ICAX4Z = $2D
            0140 ICAX5Z = $2E
            0150 ;
            0160     *=  $E6F4
            0170 ;
            0180     TAX
            0190     LDA ICAX4Z
            0200     PHA
            0210     LDA ICAX3Z
            0220     PHA
            0230     TXA
            0240     LDX ICAX5Z
            0250     RTS
    Zastosowana sztuczka polega na tym, że bajty adresu procedury pobrane z rejestrów ICAX3/4Z są umieszczane na stosie. Wykonanie teraz rozkazu RTS powoduje zdjęcie ze stosu dwóch znajdujących się tam bajtów, które normalnie oznaczają stan licznika rozkazów w chwili wykonania rozkazu JSR, zwiększenie ich o jeden i umieszczenie w liczniku rozkazów procesora. W ten sposób dalsze wykonywanie programu odbywa się od początku odpowiedniej procedury obsługi urządzenia. Kończący tą procedurę rozkaz RTS spowoduje powrót do miejsca wywołania CIOJMP, a więc bezpośrednio do procedury GOHAND. Oczywiste jest już także umieszczenie w tabeli adresowej adresów procedur zmniejszonych o jeden.

2.3. Procedura otwarcia IOCB

    Rozpoznanie przez CIOMAIN kodu operacji OPEN ($03) powoduje wywołanie procedury CIOOPN. Dla jej poprawnego wykonania rejestr ICBUFA musi zawierać adres nazwy urządzenia, dla którego otwierany jest kanał IOCB (np. S: lub D:NAZWA.EXT). Ponadto w ICAX1 muszą znajdować się informacje o sposobie dostępu do urządzenia (zapis czy odczyt) i ewentualnie inne informacje zależne od rodzaju urządzenia. Niektóre urządzenia wymagają jeszcze dodatkowych danych w rejestrze ICAX2.
            0100 ;CIO OPeN routine
            0110 ;
            0120 CIORET = $E670
            0130 CMPENT = $E695
            0140 CPLCIO = $E672
            0150 DEVNUM = $E6FF
            0160 DVSTAT = $02EA
            0170 GOHAND = $E6EA
            0180 HNDLOD = $02E9
            0190 ICAX3Z = $2C
            0200 ICAX4Z = $2D
            0210 ICCOMT = $17
            0220 ICHIDZ = $20
            0230 ICPTZ = $26
            0240 SPCHND = $EEF9
            0250 ;
            0260     *=  $E53F
            0270 ;
            0280     LDA ICHIDZ
            0290     CMP #$FF
            0300     BEQ OPN
            0310     LDY #$81
            0320 EXIT JMP CIORET
            0330 OPN LDA HNDLOD
            0340     BNE END
            0350     JSR DEVNUM
            0360     BCS END
            0370     LDA #$00
            0380     STA DVSTAT
            0390     STA DVSTAT+1
            0400 ;INItialize for OPeN
            0410 INIOPN JSR CMPENT
            0420     BCS EXIT
            0430     JSR GOHAND
            0440     LDA #$0B
            0450     STA ICCOMT
            0460     JSR CMPENT
            0470     LDA ICAX3Z
            0480     STA ICPTZ
            0490     LDA ICAX4Z
            0500     STA ICPTZ+1
            0510     JMP CPLCIO
            0520 END JSR SPCHND
            0530     JMP CIORET
    Przede wszystkim na początku procedury sprawdzany jest indeks wpisu w HATABS. Gdy jest on różny od $FF, to w rejestrze Y umieszczany jest kod błędu $81 (PREVIOUS OPEN - uprzednio otwarty) i następuje skok do CIORET. Ma to na celu zabezpieczenie przed jednoczesnym otwarciem tego samego kanału IOCB dla dwóch różnych urządzeń.

    Następnie kontrolowany jest rejestr HNDLOD, który wskazuje użycie nowego urządzenia i wywoływana jest procedura DEVNUM w celu odszukania wpisu urządzenia w HATABS. Negatywny wynik którejkolwiek z tych operacji powoduje wywołanie specjalnej procedury obsługi SPCHND, a następnie skok do CIORET.

    Jeśli wpis urządzenia w HATABS został odnaleziony, to procedura CMPENT odczytuje z tabeli adresowej urządzenia adres procedury otwierającej kanał dla tego urządzenia. Następujące po tym sprawdzenie pozytywnego wyniku jest konieczne ze względu na to, że niektóre procedury komunikacji z urządzeniami zewnętrznymi korzystają z CIOOPN od miejsca oznaczonego etykietą INIOPN.

    Teraz poprzez GOHAND jest wywoływana właściwa procedura otwarcia urządzenia. Po jej zakończeniu w rejestrze ICSTZ znajduje się status wykonanej operacji informujący o jej pomyślnym (lub nie) przebiegu.

    W ostatniej fazie procedury do rejestru ICCOMT wpisywany jest kod rozkazu PUT BYTE i ponownie wywoływana jest procedura CMPENT. Odnaleziony przez nią adres procedury PUT BYTE urządzenia jest przepisywany do rejestru ICPTZ. Procedura CIOOPN kończy się skokiem do CPLCIO.

    Po zakończeniu procedury CIOOPN odpowiedni IOCB zawiera: w rejestrze ICCHID - indeks wpisu urządzenia w HATABS, w rejestrze ICDNO - numer urządzenia oraz w rejestrze ICSTAT - wynik (status) operacji OPEN.

2.4. Procedura zamknięcia IOCB

    Kod operacji CIO równy $0C powoduje wywołanie procedury CIOCLS, której zadaniem jest zamknięcie odpowiedniego kanału IOCB. Operacja CLOSE nie wymaga żadnych dodatkowych informacji w rejestrach IOCB.
            0100 ;CIO CLoSe routine
            0110 ;
            0120 CIONOPN = $E4DC
            0130 CPLCIO = $E672
            0140 CMPENT = $E695
            0150 GOHAND = $E6EA
            0160 ICHIDZ = $20
            0170 ICPTZ = $26
            0180 ICSTZ = $23
            0190 ;
            0200     *=  $E57C
            0210 ;
            0220     LDY #$01
            0230     STY ICSTZ
            0240     JSR CMPENT
            0250     BCS CLS
            0260     JSR GOHAND
            0270 CLS LDA #$FF
            0280     STA ICHIDZ
            0290     LDA # >[CIONOPN-1]
            0300     STA ICPTZ+1
            0310     LDA # <[CIONOPN-1]
            0320     STA ICPTZ
            0330     JMP CPLCIO
    Od razu na początku procedury status operacji jest ustawiany na $01 (SUCCESS). Następnie przez procedurę CMPENT wyszukiwany jest adres procedury zamykającej komunikację z urządzeniem i procedura ta jest wywoływana poprzez GOHAND.

    Zarówno w przypadku nieodnalezienia przez CMPENT odpowiedniego wpisu w HATABS, jak i po zakończeniu procedury GOHAND (ewentualny błąd jest przez nią sygnalizowany w rejestrze ICSTZ) dalsze postępowanie jest identyczne. Indeks wpisu urządzenia w HATABS jest ustawiany na wartość $FF, a wektor procedury obsługi w rejestrze ICPTZ wskazuje na procedurę CIONOPN. Procedura ta umieszcza jedynie w rejestrze Y kod błędu $85 (NOT OPEN).
            0100 ;CIO Not OPeN
            0110 ;
            0120     *=  $E4DC
            0130 ;
            0140     LDY #$85
            0150     RTS
    Po zakończeniu operacji CLOSE rejestr ICCHID ma więc wartość $FF, a w rejestrze ICSTAT znajduje się wynik operacji.

2.5. Procedura odczytu z urządzenia

    Procedura odczytu CIO jest wywoływana po rozpoznaniu kodu $07 (GET BYTE) lub $05 (GET RECORD). Obie operacje są wykonywane przez tą samą procedurę, która rozpoznaje różnicę według bitu 1 kodu operacji (ustawiony = BYTE, skasowany = RECORD). Przed wywołaniem CIOMAIN konieczne jest jeszcze umieszczenie w rejestrze ICBUFA adresu bufora i w rejestrze ICBUFL jego długości. Jeżeli długość bufora jest równa zero, to odczytany znak umieszczany jest w akumulatorze. Zamieszczony poniżej schemat ukazuje przybliżoną strukturę operacji odczytu.
                   < CIOREAD >
                        |
                        v
                    /-------\
                   /   czy   \ nie
                  < dozwolony >---->----+
                   \ odczyt? /          |
                    \-------/           v
                        | tak       +-------+
                        v           | Y=$83 |
                  ++--------++      +-------+
                  || CMPENT ||          |
                  ++--------++          |
                        |               |
                        v               |
                     /-----\ tak        |
                    < błąd? >---->---+  |
                     \-----/         |  |
                        | nie        v  v
                        v         +--------+
          +------------>+         | CIORET |
          |             |         +--------+
          |             v
          |         +--------+
          |         | odczyt |
          |         | bajtu  |
          |         +--------+
          |             |
          |             v
          |          /-----\ tak
          |         < błąd? >---->---+
          |          \-----/         |
          |             | nie        |
          |             v            |
          |     nie /-------\ tak    v
          +---<----< koniec? >------>+
                    \-------/        |
                                     v
                                +--------+
                                | CPLCIO |
                                +--------+

          Rys.6. Struktura operacji READ
    Przed rozpoczęciem operacji odczytu kontrolowany jest bit 2 rejestru ICAX1, który sygnalizuje możliwość odczytu z urządzenia. Jeśli jest on skasowany, to do rejestru Y wpisywany jest kod błędu $83 (WRITE ONLY - dozwolony tylko zapis) i operacja kończy się skokiem do CIORET. Następnie procedura CMPENT odszukuje adres procedury odczytu z urządzenia, a w przypadku niepowodzenia także przechodzi się do CIORET (w takim razie rejestr Y zawiera kod $85 - NOT OPEN).
            0100 ;CIO READ routine
            0110 ;
            0120 CIORET = $E670
            0130 CPLCIO = $E672
            0140 DECBUFL = $E6BB
            0150 DECBUFP = $E6C8
            0160 CMPENT = $E695
            0170 GOHAND = $E6EA
            0180 ICAX1Z = $2A
            0190 ICAX6Z = $2F
            0200 ICBAZ = $24
            0210 ICBLZ = $28
            0220 ICCOMZ = $22
            0230 ICSTZ = $23
            0240 INCBUFP = $E6D1
            0250 SUBBUFL = $E6D8
            0260 ;
            0270     *=  $E5B2
            0280 ;
            0290     LDA ICCOMZ
            0300     AND ICAX1Z
            0310     BNE PRFM
            0320     LDY #$83
            0330 EXIT JMP CIORET
            0340 PRFM JSR CMPENT
            0350     BCS EXIT
            0360     LDA ICBLZ
            0370     ORA ICBLZ+1
            0380     BNE GET1
            0390     JSR GOHAND
            0400     STA ICAX6Z
            0410     JMP CPLCIO
            0420 GET1 JSR GOHAND
            0430     STA ICAX6Z
            0440     BMI END
            0450     LDY #$00
            0460     STA (ICBAZ),Y
            0470     JSR INCBUFP
            0480     LDA ICCOMZ
            0490     AND #$02
            0500     BNE NEXT
            0510     LDA ICAX6Z
            0520     CMP #$9B
            0530     BNE NEXT
            0540     JSR DECBUFL
            0550     JMP END
            0560 NEXT JSR DECBUFL
            0570     BNE GET1
            0580     LDA ICCOMZ
            0590     AND #$02
            0600     BNE END
            0610 GET2 JSR GOHAND
            0620     STA ICAX6Z
            0630     BMI ZBF
            0640     LDA ICAX6Z
            0650     CMP #$9B
            0660     BNE GET2
            0670     LDA #$89
            0680     STA ICSTZ
            0690 ZBF JSR DECBUFP
            0700     LDY #$00
            0710     LDA #$9B
            0720     STA (ICBAZ),Y
            0730     JSR INCBUFP
            0740 END JSR SUBBUFL
            0750     JMP CPLCIO
    Właściwy odczyt rozpoczyna się od sprawdzenia długości bufora. Gdy jest ona równa zero, to poprzez wywołanie GOHAND odczytywany jest do akumulatora bajt z urządzenia. Po jego przepisaniu do rejestru ICAX6Z procedura kończy się skokiem do CPLCIO.

    Przy niezerowej długości bufora postępowanie jest podobne, lecz zamiast zakończenia odczytu następuje sprawdzenie statusu operacji. Ewentualne wystąpienie błędu przerywa odczyt (przed opuszczeniem CIOREAD korygowana jest jeszcze długość bufora).

    Prawidłowo odczytany bajt jest przepisywany z akumulatora w miejsce określone zawartością rejestru ICBAZ. Aby następny znak został wpisany w kolejne miejsce pamięci, to zawartość ICBAZ jest zwiększane przez procedurę INCBUFP.
            0100 ;INCrement BUFfer Pointer
            0110 ;
            0120 ICBAZ = $24
            0130 ;
            0140     *=  $E6D1
            0150 ;
            0160     INC ICBAZ
            0170     BNE END
            0180     INC ICBAZ+1
            0190 END RTS
    Teraz kontrolowany jest bit 1 kodu operacji, który określa jej rodzaj (zob. wyżej). Gdy odczytywany jest bajt, to CIOREAD kończy się po zmniejszeniu rejestru określającego długość bufora (poprzez procedurę DECBUFL). Dla wybrania odpowiedniego wariantu procedury bit 1 jest kontrolowany potem jeszcze raz. Przy odczytywaniu rekordu trzeba sprawdzić, czy odczytany znak jest kodem końca linii ($9B - RETURN). Jeżeli tak, to po zmniejszeniu długości bufora odczyt również się kończy.

    W przeciwnym razie także zmniejszana jest długość bufora i gdy jest większa od zera, to procedura odczytu bajtu jest powtarzana. W celu zmniejszenia wskaźnika długości bufora (ICBLZ) wywoływana jest specjalna procedura DECBUFL. Zwraca ona w akumulatorze wartość zero, jeśli długość bufora jest równa zero lub wartość niezerową w przeciwnym wypadku, co ułatwia wybór wariantu procedury.
            0100 ;DECrement BUFfer Length
            0110 ;
            0120 ICBLZ = $28
            0130 ;
            0140     *=  $E6BB
            0150 ;
            0160     LDA ICBLZ
            0170     BNE SKIP
            0180     DEC ICBLZ+1
            0190 SKIP DEC ICBLZ
            0200     LDA ICBLZ
            0210     ORA ICBLZ+1
            0220     RTS
    Jeżeli cały bufor został już zapełniony (długość bufora równa zero), to procedura GOHAND jest wywoływana w pętli w celu 2odczytania pozostałej części rekordu. Odczytane bajty nie są nigdzie przechowywane i zostają stracone. Pętla jest przerywana po wystąpieniu błędu lub po napotkaniu kodu RETURN ($9B). W tym ostatnim przypadku w rejestrze Y umieszczany jest kod błędu $89 (TRUNCATED RECORD - część rekordu utracona). Ponieważ bufor jest już pełny, to procedura DECBUFP zmniejsza jego adres o jeden.
            0100 ;DECrement BUFfer Pointer
            0110 ;
            0120 ICBAZ = $24
            0130 ;
            0140     *=  $E6C8
            0150 ;
            0160     LDA ICBAZ
            0170     BNE END
            0180     DEC ICBAZ+1
            0190     DEC ICBAZ
            0200 END RTS
    W uzyskane w ten sposób miejsce wpisywany jest znak RETURN i adres bufora jest ponownie zwiększany przez procedurę INCBUFP.

    Po wszystkich opisanych wyżej wariantach zakończenia odczytu, przed opuszczeniem CIOREAD jest jeszcze wywoływana procedura SUBBUFL, której zadaniem jest uaktualnienie długości bufora dla operacji CIO. Wykorzystuje ona do rozpoznania właściwego IOCB jego numer zapisany w rejestrze ICAX5Z.
            0100 ;SUBtract BUFfer Length
            0110 ;
            0120 ICAX5Z = $2E
            0130 ICBLZ = $28
            0140 ICBUFL = $0348
            0150 ;
            0160     *=  $E6D8
            0170 ;
            0180     LDX ICAX5Z
            0190     SEC
            0200     LDA ICBUFL,X
            0210     SBC ICBLZ
            0220     STA ICBLZ
            0230     LDA ICBUFL+1,X
            0240     SBC ICBLZ+1
            0250     STA ICBLZ+1
            0260     RTS
    Procedura odejmuje od początkowej długości bufora wpisanej w ICBUFL długość jego części zajętej przez odczytane dane (zawiera ją rejestr ICBLZ). W wyniku otrzymujemy długość pozostałej jeszcze (pustej) części bufora.

    Po zapoznaniu się z przebiegiem CIOREAD można łatwo określić różnicę pomiędzy operacjami GET BYTE i GET RECORD. Przy odczycie rekordu znak RETURN ($9B) przerywa odczyt, a jego brak powoduje przepełnienie bufora i utratę części informacji. Operacja GET BYTE kończy się natomiast po zapełnieniu bufora, a znak o kodzie $9B jest traktowany tak, jak wszystkie pozostałe.

2.6. Procedura zapisu na urządzenie.

    Kody operacji $09 (PUT RECORD) i $0B (PUT BYTE) powodują wywołanie z CIOMAIN procedury CIOWRT. Przebiega ona w sposób bardzo zbliżony do procedury CIOREAD, a wymagane dla niej parametry są identyczne (ICBUFA i ICBUFL). Struktura procedury CIOWRT jest pokazana na rysunku 7.
                   < CIOWRT >
                        |
                        v
                    /-------\
                   /   czy   \ nie
                  < dozwolony >---->----+
                   \ zapis ? /          |
                    \-------/           v
                        | tak       +-------+
                        v           | Y=$87 |
                  ++--------++      +-------+
                  || CMPENT ||          |
                  ++--------++          |
                        |               |
                        v               |
                     /-----\ tak        |
                    < błąd? >---->---+  |
                     \-----/         |  |
                        | nie        v  v
                        v         +--------+
          +------------>+         | CIORET |
          |             |         +--------+
          |             v
          |         +-------+
          |         | zapis |
          |         | bajtu |
          |         +-------+
          |             |
          |             v
          |          /-----\ tak
          |         < błąd? >---->---+
          |          \-----/         |
          |             | nie        |
          |             v            |
          |     nie /-------\ tak    v
          +---<----< koniec? >------>+
                    \-------/        |
                                     v
                                +--------+
                                | CPLCIO |
                                +--------+

          Rys.7. Struktura operacji WRITE
    Podobnie jak przy odczycie na początku kontrolowany jest bit 3 rejestru ICAX1, który sygnalizuje możliwość zapisu na urządzenie. Jeśli jest on skasowany, to do rejestru Y wpisywany
      0100 ;CIO WRiTe routine
      0110 ;
      0120 CIORET = $E670
      0130 CPLCIO = $E672
      0140 CMPENT = $E695
      0150 DECBUFL = $E6BB
      0160 GOHAND = $E6EA
      0170 ICAX1Z = $2A
      0180 ICAX6Z = $2F
      0190 ICBAZ = $24
      0200 ICBLZ = $28
      0210 ICCOMZ = $22
      0220 INCBUFP = $E6D1
      0230 SUBBUFL = $E6D8
      0240 ;
      0250     *=  $E61E
      0260 ;
      0270     LDA ICCOMZ
      0280     AND ICAX1Z
      0290     BNE PRFM
      0300     LDY #$87
      0310 EXIT JMP CIORET
      0320 PRFM JSR CMPENT
      0330     BCS EXIT
      0340     LDA ICBLZ
      0350     ORA ICBLZ+1
      0360     BNE LBF
      0370     LDA ICAX6Z
      0380     INC ICBLZ
      0390     BNE PUT
      0400 LBF LDY #$00
      0410     LDA (ICBAZ),Y
      0420     STA ICAX6Z
      0430 PUT JSR GOHAND
      0440     PHP
      0450     JSR INCBUFP
      0460     JSR DECBUFL
      0470     PLP
      0480     BMI END
      0490     LDA ICCOMZ
      0500     AND #$02
      0510     BNE NEXT
      0520     LDA ICAX6Z
      0530     CMP #$9B
      0540     BEQ END
      0550 NEXT LDA ICBLZ
      0560     ORA ICBLZ+1
      0570     BNE LBF
      0580     LDA ICCOMZ
      0590     AND #$02
      0600     BNE END
      0610     LDA #$9B
      0620     JSR GOHAND
      0630 END JSR SUBBUFL
      0640     JMP CPLCIO
jest kod błędu $87 (READ ONLY - dozwolony tylko odczyt) i operacja kończy się skokiem do CIORET. Następnie przez CMPENT wyszukiwany jest adres procedury zapisu (w przypadku niepowodzenia skok do CIORET z kodem $85 w rejestrze Y).

    Poprzez sprawdzenie długości bufora określane jest miejsce pobrania znaku do wysłania. Jeżeli bufor ma zerową długość, to znak pobierany jest z akumulatora, w przeciwnym razie wysyłany jest pierwszy znak z bufora. Samo wysłanie bajtu, który zostaje przepisany do ICAX6Z, jest wykonywane przez wywołanie procedury obsługi urządzenia poprzez GOHAND. Następnie przez wywołanie INCBUFP i DECBUFL zwiększany jest adres bufora i zmniejszana jego długość.

    Teraz wykonywana jest seria sprawdzeń różnych warunków. Procedura zapisu jest przerywana, jeśli wystąpił błąd przy zapisie, jeśli zapisywany był bajt (PUT BYTE) i długość bufora jest równa zero lub jeśli przy zapisywaniu rekordu został wysłany znak RETURN. Jeżeli przy zapisie bajtów długość bufora jest różna od zera, to następny bajt z bufora jest przepisywany do ICAX6Z i zapis jest powtarzany. Zerowa długość bufora w przypadku zapisu rekordu powoduje jeszcze przed zakończeniem operacji zapisanie bajtu $9B (RETURN).

    We wszystkich wymienionych przypadkach zakończenia operacji zapisu, przed opuszczeniem CIOWRT jest jeszcze uaktualniana długość bufora (przy pomocy SUBBUFL). Cała operacja zapisu kończy się skokiem do CPLCIO.

    Dokładniejsze informacje o procedurach DECBUFL, INCBUFP i SUBBUFL znajdują się w rozdziale 2.5. (Procedura odczytu z urządzenia).

2.7. Odczyt statusu i procedury specjalne

    Wszystkie kody operacji o wartości równej lub większej od $0D powodują wywołanie procedury CIOSTSP. Kod $0D oznacza operację odczytu statusu urządzenia, zaś wyższe kody są rozkazami operacji specjalnych, których przebieg zależy od rodzaju urządzenia.

    Procedura ta, jako jedyna z procedur CIO, umożliwia wykonanie operacji BEZ uprzedniego otwierania urządzenia operacją OPEN. Najpierw sprawdzany jest bowiem indeks wpisu w HATABS (zawarty w rejestrze ICHIDZ). Jeżeli ma on wartość $FF, to wywoływana jest procedura DEVNUM, która wyszukuje prawidłowy indeks (wystąpienie przy tym błędu przerywa operację skokiem do CIORET).
            0100 ;CIO STatus/SPecial routine
            0110 ;
            0120 CPLCIO = $E672
            0130 CMPENT = $E695
            0140 DEVNUM = $E6FF
            0150 GOHAND = $E6EA
            0160 ICAX5Z = $2E
            0170 ICCHID = $0340
            0180 ICHIDZ = $20
            0190 ;
            0200     *=  $E597
            0210 ;
            0220     LDA ICHIDZ
            0230     CMP #$FF
            0240     BNE PRFM
            0250     JSR DEVNUM
            0260     BCS $E547     ;do JMP CIORET
            0270 PRFM JSR CMPENT
            0280     JSR GOHAND
            0290     LDX ICAX5Z
            0300     LDA ICCHID,X
            0310     STA ICHIDZ
            0320     JMP CPLCIO
    Dalszy przebieg procedury CIOSTSP jest podobny do opisanych wcześniej. Adres sterownika jest odszukiwany przez wywołanie CMPENT, a sama procedura obsługi wywoływana jest poprzez GOHAND. Ponieważ podczas procedury CIOMAIN zmieniane są kody operacji większe od $0D, to przed zakończeniem CIOSTSP prawidłowy kod jest odtwarzany według zawartości właściwego IOCB. Procedura kończy się skokiem do CPLCIO.
Zientara Wojciech: Mapa pamięci Atari XL/XE. Procedury wejścia-wyjścia, SOETO, Warszawa, 1988.