Powrót do spisu treści

Rozdział 6

PROCEDURY WYKONAWCZE INSTRUKCJI

    Opisywana w rozdziale 2 procedura EXSTM w celu wykonania instrukcji Basica pobiera z tablicy wektorów STVTAB adres odpowiedniej procedury realizacyjnej, a następnie wywołuje ją. Po opisie wszystkich pozostałych elementów programu nadeszła więc pora na przedstawienie procedur wykonawczych poszczególnych instrukcji zaimplementowanych w interpreterze Atari Basic. Procedury te zostały podzielone na grupy w zależności od funkcji spełnianych w programie przez te instrukcje.

6.1. Instrukcje kontroli programu

    Instrukcjami kontroli programu nazywamy takie, które sterują bezpośrednio pracą interpretera, a także realizacją programu. Należą do nich instrukcje: NEW, BYE, DOS, END, STOP, CONT, RUN i CLR.

6.1.1. Instrukcja NEW

    Instrukcja NEW kasuje program w Basicu zawarty w pamięci komputera oraz wszystkie wykorzystywane przez niego zmienne i ich wartości. Jest ona częścią składową procedury zimnego startu CDST i została opisana razem z nią. Analiza tej procedury ujawnia, że wszystkie dane programu po jej wykonaniu nadal pozostają w pamięci. Skasowane zostają tylko wskazujące je wektory. Odzyskanie w całości skasowanego programu jest jednak niemożliwe, gdyż wpisanie kolejnej instrukcji zniszczy jego część. Pewne fragmenty można wszakże odtworzyć.

6.1.2. Instrukcja BYE

    Instrukcja BYE powoduje zakończenie pracy interpretera i przejście do wbudowanego programu testującego. Jej procedura wykonawcza - XBYE - składa się tylko z wywołania procedury CLALL, która zamyka wszystkie kanały IOCB (oprócz edytora) i wyłącza dźwięk oraz skoku do programu testującego poprzez tablicę skoków JMPTAB.
            0100 ;eXecute BYE command
            0110 ;
            0120 CLALL = $BD45
            0130 JTSTROM = $E480
            0140 ;
            0150     *=  $A9E6
            0160 ;
            0170     JSR CLALL
            0180     JMP JTSTROM

6.1.3. Instrukcja DOS

    Także instrukcja DOS przerywa pracę interpretera, lecz sterowanie komputerem przekazuje do programu, którego adres zapisany jest w rejestrze DOSVEC. Przy pracy ze stacją dysków znajduje się tam adres DOS-u (zob. "Mapa pamięci Atari XL/XE. Dyskowe systemy operacyjne"). Jeśli nie ma stacji, to rejestr DOSVEC zawiera adres programu testującego, więc działanie instrukcji DOS jest analogiczne jak BYE. Procedura wykonawcza - XDOS - jest również zbliżona do XBYE, a różni się tylko końcowym skokiem.
            0100 ;eXecute DOS command
            0110 ;
            0120 CLALL = $BD45
            0130 DOSVEC = $0A
            0140 ;
            0150     *=  $A9EC
            0160 ;
            0170     JSR CLALL
            0180     JMP (DOSVEC)

6.1.4. Instrukcja END

    Instrukcja END przerywa działanie programu, a następnie zamyka wszystkie kanały dźwięku i komunikacji z urządzeniami zewnętrznymi. Jest to realizowane w procedurze XEND przez skok do gorącego startu interpretera. Przedtem jednak przez wywołanie procedury SAVCLN w rejestrze STOPLN (STOP LiNe number) zapamiętywany jest numer aktualnego wiersza programu.
            0100 ;eXecute END statement
            0110 ;
            0120 SAVCLN = $B7A6
            0130 WRMST = $A050
            0140 ;
            0150     *=  $B78C
            0160 ;
            0170     JSR SAVCLN
            0180     JMP WRMST

6.1.5. Instrukcja STOP

    Instrukcja STOP także przerywa działanie programu, jednak nie wyłącza dźwięku i nie zamyka kanałów I/O. Efekt jej działania jest niemal identyczny z efektem wystąpienia błędu w programie. Procedura wykonawcza tej instrukcji - XSTOP - jest także wywoływana po naciśnięciu klawisza BREAK.

    Realizacja instrukcji STOP rozpoczyna się od zapamiętania w rejestrze STOPLN aktualnego numeru wiersza (przez SAVCLN) oraz wyświetlenia na ekranie znaku końca wiersza RETURN (przez PRTRET). Następnie w rejestrze POKADR umieszczany jest adres komunikatu "STOPPED", który jest wyświetlany po wywołaniu procedury PUTTXT. Dalsza część komunikatu (numer wiersza w trybie programowym lub tylko RETURN w trybie bezpośrednim) jest wyświetlana po przekazaniu sterowania do wnętrza procedury obsługi błędu poprzez skok do etykiety DSTMSG.
            0100 ;eXecute STOP statement
            0110 ;
            0120 DSTMSG = $B968
            0130 POKADR = $95
            0140 PRTRET = $BD79
            0150 PUTTXT = $B567
            0160 SAVCLN = $B7A6
            0170 STMSG = $A5FD
            0180 ;
            0190     *=  $B792
            0200 ;
            0210     JSR SAVCLN
            0220     JSR PRTRET
            0230     LDA # <STMSG
            0240     STA POKADR
            0250     LDA # >STMSG
            0260     STA POKADR+1
            0270     JSR PUTTXT
            0280     JMP DSTMSG
    Tekst komunikatu o przerwaniu pracy programu jest umieszczony w pamięci za tablicą nazw instrukcji STNAME i oznaczony etykietą STMSG.
            0100 ;STopped MeSsaGe
            0110 ;
            0120     *=  $A5FD
            0130 ;
            0140     .CBYTE "STOPPED "

6.1.6. Instrukcja CONT

    Wznowienie realizacji przerwanego programu jest wykonywane przez instrukcję CONT, a właściwie jej procedurę - XCONT. Instrukcja CONT podana w trybie programowym, co jest sprawdzane przez pierwsze wywołanie GHISTM, powoduje jedynie ustawienie rejestrów kanału I/O na kanał edytora (poprzez RSTCHN). W trybie bezpośrednim z rejestru STOPLN numer wiersza jest przepisywany do CLNN (Current LiNe Number) i procedura FNDCST odszukuje ten wiersz. Jeśli jest on w trybie bezpośrednim, to procedura jest przerywana skokiem do gorącego startu interpretera.
            0100 ;eXecute CONT statement
            0110 ;
            0120 CLNN =  $A0
            0130 FNDCST = $A9A2
            0140 GHISTM = $A9E1
            0150 GLNLEN = $A9DC
            0160 GSTMLN = $B819
            0170 NXTSTM = $A9D0
            0180 STOPLN = $BA
            0190 ;
            0200     *=  $B7B5
            0210 ;
            0220     JSR GHISTM
            0230     BPL $B7B2   ;JMP RSTCHN
            0240     LDA STOPLN
            0250     STA CLNN
            0260     LDA STOPLN+1
            0270     STA CLNN+1
            0280     JSR FNDCST
            0290     JSR GHISTM
            0300     BMI $B775   ;JMP WRMST
            0310     JSR GLNLEN
            0320     JSR NXTSTM
            0330     JSR GHISTM
            0340     BMI $B775   ;JMP WRMST
            0350     JMP GSTMLN
    Po odnalezieniu aktualnego wiersza programu odczytywana jest przy pomocy GLNLEN jego długość i procedura NXTSTM znajduje następny wiersz. Jeżeli jest on w trybie bezpośrednim, to także wykonywany jest skok do WRMST. W przeciwnym przypadku następuje skok do GSTMLN i realizacja programu jest kontynuowana. Jeśli zatrzymanie programu nastąpiło w środku wiersza, to dalsze instrukcje w tym wierszu NIE będą wykonane.

6.1.7. Instrukcje CLR i RUN

    Instrukcja CLR kasuje deklaracje zmiennych tablicowych oraz zeruje pozostałe zmienne wykorzystywane w programie. Ponadto usuwa ze stosu bieżącego wszelkie informacje o procedurach i pętlach FOR/NEXT. Instrukcja RUN powoduje natomiast uruchomienie programu znajdującego się w pamięci komputera lub odczytanie programu z urządzenia zewnętrznego i jego uruchomienie. Procedura wykonawcza instrukcji CLR (oznaczona etykietą XCLR) jest częścią składową procedury XRUN, która realizuje instrukcję RUN. Z tego powodu zostały one opisane łącznie.
            0100 ;eXecute RUN statement
            0110 ;
            0120 CLNN =  $A0
            0130 CLRVV = $B8B9
            0140 DATAD = $B6
            0150 DATALN = $B7
            0160 FSTGLN = $B816
            0170 GETIX = $B904
            0180 GHISTM = $A9E1
            0190 LDPRGM = $BAF7
            0200 RSMEMT = $B8A8
            0210 RSTBRG = $B8F1
            0220 WRMST = $A050
            0230 ;
            0240     *=  $B74C
            0250 ;
            0260 XRUN JSR GETIX
            0270     BCS RUN
            0280     JSR LDPRGM
            0290 RUN NOP
            0300     LDA #$00
            0310     STA CLNN
            0320     STA CLNN+1
            0330     JSR FSTGLN
            0340     JSR GHISTM
            0350     BMI END
            0360     JSR RSTBRG
            0370 ;
            0380 ;eXecute CLR statement
            0390 ;
            0400 XCLR JSR CLRVV
            0410     JSR RSMEMT
            0420     LDA #$00
            0430     STA DATALN
            0440     STA DATALN+1
            0450     STA DATAD
            0460     RTS
            0470 END JMP WRMST
    Najpierw rozpoznawany jest rodzaj instrukcji RUN, to znaczy, czy program do uruchomienia znajduje się już w pamięci, czy musi być najpierw odczytany. W tym celu porównywane są przez procedurę GETIX indeksy wejściowy (INIX) i wyjściowy (OUTIX). Jeśli indeks wejściowy jest większy, to wywoływana jest procedura LDPRGM (jest ona fragmentem XLOAD), która odczytuje program ze wskazanego urządzenia.
            0100 ;GET IndeX
            0110 ;
            0120 INIX =  $A8
            0130 OUTIX = $A7
            0140 ;
            0150     *=  $B904
            0160 ;
            0170     LDX INIX
            0180     INX
            0190     CPX OUTIX
            0200     RTS
    Sposób uruchomienia programu jest bardzo prosty. Najpierw zerowany jest rejestr CLNN, a następnie procedura FSTGLN odszukuje wiersz o najniższym numerze. Jeśli jest to wiersz w trybie bezpośrednim (numer $8000), to procedura jest przerywana skokiem do WRMST. Jeżeli nie, to kanały I/O są zamykane, a rejestry Basica zerowane przez procedurę RSTBRG.

    Teraz rozpoczyna się procedura XCLR. Na początku zerowane są wszystkie zmienne liczbowe oraz informacje o zmiennych tekstowych i tablicowych. Wykonuje to procedura CLRVV, która wypełnia zerami prawie całą tablicę wartości zmiennych. Nienaruszone pozostają tylko bajty określające numery i typy zmiennych.
            0100 ;CLeaR Variable Value
            0110 ;
            0120 STMTAB = $88
            0130 VVTP =  $86
            0140 ZTEMP1 = $F5
            0150 ;
            0160     *=  $B8B9
            0170 ;
            0180     LDX VVTP
            0190     STX ZTEMP1
            0200     LDY VVTP+1
            0210     STY ZTEMP1+1
            0220 LOOP LDX ZTEMP1+1
            0230     CPX STMTAB+1
            0240     BCC EXEC
            0250     LDX ZTEMP1
            0260     CPX STMTAB
            0270     BCC EXEC
            0280     RTS
            0290 EXEC LDY #$00
            0300     LDA (ZTEMP1),Y
            0310     AND #$FE
            0320     STA (ZTEMP1),Y
            0330     LDY #$02
            0340     LDX #$06
            0350     LDA #$00
            0360 NEXT STA (ZTEMP1),Y
            0370     INY
            0380     DEX
            0390     BNE NEXT
            0400     LDA ZTEMP1
            0410     CLC
            0420     ADC #$08
            0430     STA ZTEMP1
            0440     LDA ZTEMP1+1
            0450     ADC #$00
            0460     STA ZTEMP1+1
            0470     BNE LOOP
    Kolejnym krokiem jest skasowanie tablicy zmiennych tablicowych i tekstowych oraz stosu bieżącego. Ta operacja jest wykonywana przez procedurę RSMEMT. Polega ona na przepisaniu wektora STARP (STring and ARray Pointer) do wektorów RUNSTK (RUNtime STacK), BMEMHI (Basic MEMory HIgh) oraz APPMHI (APPlication Memory HIgh - wykorzystywany przez system operacyjny).
            0100 ;ReStore MEMory Top
            0110 ;
            0120 APPMHI = $0E
            0130 BMEMHI = $90
            0140 RUNSTK = $8E
            0150 STARP = $8C
            0160 ;
            0170     *=  $B8A8
            0180 ;
            0190     LDA STARP
            0200     STA RUNSTK
            0210     STA BMEMHI
            0220     STA APPMHI
            0230     LDA STARP+1
            0240     STA RUNSTK+1
            0250     STA BMEMHI+1
            0260     STA APPMHI+1
            0270     RTS
    Ostatnim etapem jest odtworzenie stanu początkowego liczników danych zapisanych w instrukcjach DATA. Uzyskuje się to przez wpisanie zer do rejestrów DATAD (DATa ADdress) i DATALN (DATA LiNe number).

    Uruchomienie programu następuje zawsze od wiersza o najmniejszym numerze. Jest to jednak możliwe do ominięcia przy pomocy krótkiej procedury maszynowej. Musi ona umieścić w rejestrze CLNN numer wiersza, od którego będzie rozpoczęte wykonywanie programu, a następnie wykonać skok do wnętrza XRUN do adresu $B75B.

6.2. Instrukcje pomocnicze

    Kolejna grupa instrukcji pełni rolę pomocniczą, lecz prawidłowe działanie programu jest bez nich niemożliwe lub przynajmniej utrudnione. Znajdują się tu także instrukcje, których nie można zaliczyć do żadnej z pozostałych grup. Są to: REM, DATA, DEG, RAD, RESTORE, DIM i POKE.

6.2.1. Instrukcje REM i DATA

    Instrukcja REM zawiera komentarz wpisywany przez programistę w celu zwiększenia przejrzystości programu lub podania istotnych informacji. Natomiast w instrukcji DATA są umieszczane dane dla instrukcji READ. Obie te instrukcje są w trakcie wykonywania programu pomijane przez interpreter. Procedura wykonawcza tych instrukcji ogranicza się więc tylko do rozkazu RTS. Rozkaz ten znajduje się w procedurze GHISTM, która została opisana w rozdziale 2.

6.2.2. Instrukcje DEG i RAD

    Instrukcje DEG i RAD ustalają podstawę do obliczeń funkcji trygonometrycznych. DEG powoduje traktowanie wszystkich argumentów kątowych, jako podanych w stopniach, zaś RAD - jako podanych w radianach. Odpowiednio procedury wykonawcze tych instrukcji umieszczają w rejestrze RADFLG (RADians FLaG) wartości sześć lub zero.
            0100 RADFLG = $FB
            0110 ;
            0120     *=  $B28D
            0130 ;
            0140 ;eXecute DEG statement
            0150 ;
            0160 XDEG LDA #$06
            0170     BNE EXE
            0180 ;
            0190 ;eXecute RAD statement
            0200 ;
            0210 XRAD LDA #$00
            0220 EXE STA RADFLG
            0230     RTS

6.2.3. Instrukcja RESTORE

    Instrukcja RESTORE ustawia znacznik odczytu danych z instrukcji DATA na początek wiersza, którego numer został podany jako argument. Jeśli instrukcja nie ma argumentu, to znacznik jest ustawiany na pierwszy wiersz programu. Operacja ta jest przeprowadzana przez procedurę XRSTR. W każdym przypadku najpierw zerowany jest rejestr DATAD, co ustawia znacznik na pierwszej danej w odpowiedniej instrukcji DATA.
            0100 ;eXecute RESTORE statement
            0110 ;
            0120 DATAD = $B6
            0130 DATALN = $B7
            0140 FR0 =   $D4
            0150 GETIX = $B904
            0160 GLNNUM = $ABCD
            0170 ;
            0180     *=  $B296
            0190 ;
            0200     LDA #$00
            0210     STA DATAD
            0220     JSR GETIX
            0230     BCC GLN
            0240     TAY
            0250     BEQ SLN
            0260 GLN JSR GLNNUM
            0270     LDA FR0+1
            0280     LDY FR0
            0290 SLN STA DATALN+1
            0300     STY DATALN
            0310     RTS
    Następnie przez wywołanie procedury GETIX sprawdzane są indeksy (podobnie jak w XRUN). Jeśli instrukcja posiada argument, to zostaje on odczytany przez procedurę GLNNUM i przepisany do rejestru DATALN. W przeciwnym przypadku rejestr DATALN jest zerowany.
            0100 ;Get LiNe NUMber
            0110 ;
            0120 FR0 =   $D4
            0130 LETNUM = $ABD7
            0140 LINNER = $B926
            0150 ;
            0160     *=  $ABCD
            0170 ;
            0180     JSR LETNUM
            0190     LDA FR0+1
            0200     BPL $ABC9   ;RTS
            0210     JMP LINNER
    Procedura GLNNUM wykorzystuje do odczytu dwubajtowej wartości procedurę LETNUM. Po sprawdzeniu, czy uzyskany wynik nie przekracza dopuszczalnej wartości ($7FFF), GLNNUM się kończy. Jeśli jednak wartość nie jest poprawna, to przez skok do procedury LINNER sygnalizowany jest błąd (LINe Number ERror).

6.2.4. Instrukcja DIM

    Instrukcja DIM służy do deklarowania wymiarów zmiennych tablicowych i tekstowych. Atari Basic wymaga zadeklarowania wszystkich takich zmiennych przed ich użyciem. Do realizacji tej instrukcji przeznaczona jest procedura XDIM.

    Ponieważ instrukcja DIM może zawierać deklaracje kilku zmiennych, to procedura XDIM przebiega w pętli, która jest sterowana licznikami INIX i OUTIX. Każde przejście pętli rozpoczyna się od odczytania typu zmiennej. Jeśli była ona wcześniej deklarowana (ustawiony bit 0 rejestru VART), to błąd sygnalizowany jest przez skok do DIMER.
            0100 ;eXecute DIM statement
            0110 ;
            0120 CSTAD = $97
            0130 DIMER = $B922
            0140 EVZTMP = $AF48
            0150 FR0 =   $D4
            0160 INIX =  $A8
            0170 INSEL = $A87A
            0180 OUTIX = $A7
            0190 RUNSTK = $8E
            0200 SAVVAL = $AC0C
            0210 STARP = $8C
            0220 VART =  $D2
            0230 XLET =  $AADA
            0240 ZFR0 =  $DA44
            0250 ZT1ML6 = $AF31
            0260 ZTEMP1 = $F5
            0270 ;
            0280     *=  $B206
            0290 ;
            0300 XDIM LDY INIX
            0310     CPY OUTIX
            0320     BCC EXE
            0330     RTS
            0340 EXE JSR XLET
            0350     LDA VART
            0360     ROR A
            0370     BCC NUM
            0380 ERR JSR DIMER
            0390 NDM SEC
            0400     ROL A
            0410     STA VART
            0420     BMI STRNG
            0430     LDY ZTEMP1
            0440     LDX ZTEMP1+1
            0450     INY
            0460     BNE COL
            0470     INX
            0480     BMI ERR
            0490 COL STY FR0+2
            0500     STX FR0+3
            0510     STY ZTEMP1
            0520     STX ZTEMP1+1
            0530     LDY CSTAD
            0540     LDX CSTAD+1
            0550     INY
            0560     BNE ROW
            0570     INX
            0580     BMI ERR
            0590 ROW STY FR0+4
            0600     STX FR0+5
            0610     JSR EVZTMP
            0620     JST ZT1ML6
            0630     LDY ZTEMP1
            0640     LDA ZTEMP1+1
            0650     BMI ERR
            0660     BPL INS
            0670 STRNG LDA #$00
            0680     STA FR0+2
            0690     STA FR0+3
            0700     LDY ZTEMP1
            0710     STY FR0+4
            0720     LDA ZTEMP1+1
            0730     STA FR0+5
            0740     BNE INS
            0750     CPY #$00
            0760     BEQ ERR
            0770 INS LDX #RUNSTK
            0780     JSR INSEL+2
            0790     SEC
            0800     LDA CSTAD
            0810     SBC STARP
            0820     STA FR0
            0830     LDA CSTAD+1
            0840     SBC STARP+1
            0850     STA FR0+1
            0860     JSR SAVVAL
            0870     JMP XDIM
    Po ustawieniu najmłodszego bitu rejestru VART sprawdzany jest jego najstarszy bit, który wskazuje typ zmiennej. Zależnie od jego stanu wybierany jest odpowiedni wariant procedury (skasowany - zmienna liczbowa indeksowana czyli zmienna tablicowa, ustawiony - zmienna tekstowa).

    W przypadku zmiennej liczbowej indeksowanej jej wymiary są odczytywane z rejestrów ZTEMP1 oraz CSTAD i po zwiększeniu o jeden umieszczane w odpowiednich bajtach rejestru FR0. Zwiększenie jest konieczne, gdyż elementy zmiennej są numerowane od zera. Na tym etapie ponownie (uczyniła to już procedura XPDIM) sprawdzane jest, czy wartości wymiarów są mniejsze od $8000. Etap ten kończy się obliczeniem obszaru pamięci niezbędnego dla zapisania wszystkich elementów zmiennej.

    Dla zmiennej tekstowej procedura jest nieco prostsza, gdyż może ona mieć tylko jeden wymiar. Jako druga dana wpisywana jest aktualna długość ciągu, a więc zero. Ponadto nie trzeba obliczać przestrzeni zajmowanej przez zmienną.

    Ostatnia faza pętli jest również wspólna dla zmiennych obu typów. Przez wywołanie procedury INSEL rezerwowany jest w tablicy STARP obszar pamięci dla zmiennej. Aktualne parametry zmiennej są zapisywane w tablicy wartości (VVT) przez procedurę SAVVAL. Ponieważ procedura INSEL (zob. rozdział 1) nie zeruje rezerwowanego obszaru, to odczyt elementu zmiennej liczbowej da zupełnie przypadkowy wynik. Próba odczytu elementu zmiennej tekstowej spowoduje natomiast błąd długości ciągu (SLENER).

6.2.5. Instrukcja POKE

    Instrukcja POKE umieszcza liczbę podaną jako drugi argument w komórce pamięci, której adres jest pierwszym argumentem. Realizuje ją procedura XPOKE. Najpierw procedura LETNUM odczytuje dwubajtową liczbę całkowitą, która stanowi pierwszy argument. Jest ona przepisywana do rejestru POKADR (POKe ADdRess). Jednobajtowa wartość drugiego argumentu jest odczytywana z bufora przez procedurę GETBYT. Zostaje ona następnie umieszczona we wskazanym miejscu pamięci.
            0100 ;eXecute POKE statement
            0110 ;
            0120 FR0 =   $D4
            0130 GETBYT = $ABE0
            0140 LETNUM = $ABD7
            0150 POKADR = $95
            0160 ;
            0170     *=  $B278
            0180 ;
            0190     JSR LETNUM
            0200     LDA FR0
            0210     STA POKADR
            0220     LDA FR0+1
            0230     STA POKADR+1
            0240     JSR GETBYT
            0250     LDA FR0
            0260     LDY #$00
            0270     STA (POKADR),Y
            0280     RTS
    Procedura GETBYT działa dwustopniowo. Przez wywołanie GLNNUM odczytuje liczbę dwubajtową mniejszą od $8000 (dla liczb większych GLNNUM wskazuje błąd), a jeśli starszy bajt jest niezerowy, to sygnalizuje błąd przez skok do BVALER (Bad VALue ERror).
            0100 ;GET BYTe
            0110 ;
            0120 BVALER = $B92E
            0130 GLNNUM = $ABCD
            0140 ;
            0150     *=  $ABE0
            0160 ;
            0170     JSR GLNNUM
            0180     BNE ERR
            0190     RTS
            0200 ERR JSR BVALER

6.3. Instrukcje strukturalne

    Podstawowy kształt programu jest tworzony przez instrukcje strukturalne. Umożliwiają one realizację skoków, procedur i pętli oraz warunkowe wykonanie innych instrukcji. Do instrukcji strukturalnych w Atari Basic należą: POP, TRAP, GOTO, GOSUB, RETURN, FOR, NEXT, ON i IF.

6.3.1. Instrukcja POP

    Instrukcja POP zdejmuje ze stosu bieżącego informacje o ostatniej procedurze GOSUB/RETURN lub pętli FOR/NEXT. Jest to konieczne przy opuszczaniu procedury lub pętli przez skok. Instrukcja ta jest realizowana przez procedurę XPOP.
            0100 ;eXecute POP statement
            0110 ;
            0120 BMEMHI = $90
            0130 CLNN =  $A0
            0140 DELEL = $A8F7
            0150 RUNSTK = $8E
            0160 STMNUM = $B2
            0170 ;
            0180     *=  $B83E
            0190 ;
            0200     LDA RUNSTK+1
            0210     CMP BMEMHI+1
            0220     BCC POP
            0230     LDA RUNSTK
            0240     CMP BMEMHI
            0250     BCS $B83D   ;RTS
            0260 POP LDA #$04
            0270     LDX #BMEMHI
            0280     JSR DELEL
            0290     LDY #$03
            0300     LDA (BMEMHI),Y
            0310     STA STMNUM
            0320     DEY
            0330     LDA (BMEMHI),Y
            0340     STA CLNN+1
            0350     DEY
            0360     LDA (BMEMHI),Y
            0370     STA CLNN
            0380     DEY
            0390     LDA (BMEMHI),Y
            0400     BEQ END
            0410     PHA
            0420     LDA #$0C
            0430     LDX #BMEMHI
            0440     JSR DELEL
            0450     PLA
            0460 END CLC
            0470     RTS
    Procedura XPOP musi najpierw sprawdzić, czy na stosie jest coś zapisane, w przeciwnym bowiem przypadku uległaby zniszczeniu część tablicy zmiennych indeksowanych. Następnie przez wywołanie procedury DELEL wektor BMEMHI jest obniżany o cztery miejsca. Odczytane stamtąd wartości są przepisywane kolejno do rejestru numeru instrukcji STMNUM (STateMent NUMber) oraz numeru wiersza CLNN (Current LiNe Number). Ostatnia wartość pozwala na rozpoznanie rodzaju informacji zapisanej na stosie. Jeśli jest to zero, a więc informacja dotyczy procedury GOSUB, to procedura XPOP się kończy. W przeciwnym przypadku są to dane pętli FOR/NEXT (teraz już zbędne) i przez ponowne wywołanie DELEL wektor BMEMHI jest zmniejszany jeszcze o dwanaście miejsc.

6.3.2. Instrukcja TRAP

    Instrukcja TRAP ustala numer wiersza programu, od którego będzie kontynuowana praca po wystąpieniu błędu. Jej procedura wykonawcza - XTRAP - jest bardzo prosta. Numer wiersza odczytany przy pomocy LETNUM umieszczany jest w rejestrze TRAPLN (TRAP LiNe number) i to wszystko.
            0100 ;eXecute TRAP statement
            0110 ;
            0120 FR0 =   $D4
            0130 LETNUM = $ABD7
            0140 TRAPLN = $BC
            0150 ;
            0160     *=  $B7D8
            0170 ;
            0180     JSR LETNUM
            0190     LDA FR0
            0200     STA TRAPLN
            0210     LDA FR0+1
            0220     STA TRAPLN+1
            0230     RTS

6.3.3. Instrukcje GOTO i GOSUB

    Instrukcje GOTO (lub GO TO) i GOSUB służą do wykonywania skoków do innych miejsc programu. Dodatkowo GOSUB powoduje zapamiętanie adresu aktualnej instrukcji, co umożliwia potem powrót. W związku z tym ich procedury realizacyjne - XGOTO i XGOSUB - różnią się tylko jednym rozkazem, który wywołuje procedurę zapisu parametrów bieżącej instrukcji.
            0100 CLNN =  $A0
            0110 FNDCST = $A9A2
            0120 FR0 =   $D4
            0130 GLNNUM = $ABCD
            0140 LNFDER = $B91C
            0150 PRCSTM = $A95E
            0160 RSCSTM = $B6F0
            0170 SAVSTM = $B6F9
            0180 ;
            0190     *=  $B6D2
            0200 ;
            0210 ;eXecute GOSUB statement
            0220 ;
            0230 ;
            0240 XGOSUB JSR SAVSTM
            0250 ;
            0260 ;eXecute GOTO statement
            0270 ;
            0280 XGOTO JSR GLNNUM
            0290 ;
            0300 ;GO to LINE
            0310 ;
            0320 GOLINE LDA FR0+1
            0330     STA CLNN+1
            0340     LDA FR0
            0350     STA CLNN
            0360 ;
            0370 ;FinD & EXecute STatement
            0380 ;
            0390 FDEXST JSR FNDCST
            0400     BCS ERR
            0410     PLA
            0420     PLA
            0430     JMP PRCSTM
            0440 ERR JSR RSCSTM
            0450     JSR LNFDER
    Odczytanie numeru wiersza, do którego będzie wykonany skok realizuje procedura GLNNUM. Numer ten jest przepisywany do rejestru CLNN i procedura FNDCST odszukuje go w pamięci. Następnie ze stosu procesora zdejmowany jest adres powrotny dla XGOTO lub XGOSUB i po wykonaniu skoku do PRCSTM realizowany jest wskazany wiersz programu. Jeżeli nie ma w programie wiersza o podanym numerze, to przez wywołanie procedury RSCSTM odtwarzany jest aktualny numer wiersza i przez skok do LNFDER sygnalizowany jest błąd (Line Not FounD ERror).
            0100 ;ReStore Current STateMent
            0110 ;
            0120 SAVCUR = $BE
            0130 STMCUR = $8A
            0140 ;
            0150     *=  $B6F0
            0160 ;
            0170     LDA SAVCUR
            0180     STA STMCUR
            0190     LDA SAVCUR+1
            0200     STA STMCUR+1
            0210     RTS
    Podczas realizacji instrukcji GOSUB dodatkowo jest wywoływana procedura SAVSTM, która zapisuje parametry aktualnego wiersza na stosie bieżącym Basica. Składa się ona z wywołań dwóch innych procedur, przy czym PHSTK jest fragmentem procedury XFOR (rozdział 6.3.5).
            0100 ;SAVe current STateMent
            0110 ;
            0120 PHSTK = $B6B5
            0130 SAVIX = $B883
            0140 ;
            0150     *=  $B6F9
            0160 ;
            0170     JSR SAVIX
            0180     LDA #$00
            0190     BEQ PHSTK
    Druga procedura - SAVIX - przepisuje tylko aktualny stan licznika wejściowego INIX (INput IndeX) do pomocniczego rejestru TMPIX (TeMPorary IndeX).
            0100 ;SAVe IndeX
            0110 ;
            0120 INIX =  $A8
            0130 TMPIX = $B3
            0140 ;
            0150     *=  $B883
            0160 ;
            0170     LDY INIX
            0180     STY TMPIX
            0190     RTS

6.3.4. Instrukcja RETURN

    Instrukcja RETURN jest odwrotnością instrukcji GOSUB i powoduje powrót do niej, a dalszy przebieg programu jest wykonywany od instrukcji następującej po GOSUB lub ON/GOSUB. Jej procedura realizacyjna - XRTRN - jest znacznie bardziej uniwersalna i stosowana jest także dla odtworzenia aktualnego wiersza programu po wykonaniu instrukcji READ i LIST. Rozpoczyna się ona od wywoływania opisanej wyżej procedury XPOP, aż do natrafienia w ostatnim zdejmowanym ze stosu bajcie na wartość równą zero. Jeśli zaś na stosie brak takich danych, to przez skok do RETER sygnalizowany jest błąd (RETurn ERror).
            0100 ;eXecute RETURN statement
            0110 ;
            0120 FSTGLN = $B816
            0130 GOSLER = $B916
            0140 OUTIX = $A7
            0150 RETER = $B914
            0160 RSCSTM = $B6F0
            0170 STMCUR = $8A
            0180 STMNUM = $B2
            0190 XPOP =  $B83E
            0200 ;
            0210     *=  $BDA8
            0220 ;
            0230 XRTRN JSR XPOP
            0240     BCS ERR
            0250     BNE XRTRN
            0260     JSR RETURN
            0270     CMP #$0C
            0280     BEQ END
            0290     CMP #$1E
            0300     BEQ END
            0310     CMP #$04
            0320     BEQ END
            0330     CMP #$22
            0340     BEQ END
            0350 ;
            0360 ;Bad RETurn LiNe
            0370 ;
            0380 BRETLN JSR RSCSTM
            0390     JSR GOSLER
            0400 ERR JSR RETER
            0410 ;
            0420 ;RETURN
            0430 ;
            0440 RETURN JSR FSTGLN
            0450     BCS BRETLN
            0460     LDY STMNUM
            0470     DEY
            0480     LDA (STMCUR),Y
            0490     STA OUTIX
            0500     INY
            0510     LDA (STMCUR),Y
            0520 END RTS
    Następnie przez wywołanie RETURN odtwarzany jest stan licznika wyjściowego OUTIX oraz adres ostatniego wykonanego tokena, który jest ponadto odczytywany. Jeśli jest to token jednej z dozwolonych tu instrukcji - GOSUB, ON, LIST lub READ, to procedura się kończy. W przeciwnym przypadku procedura RSCSTM odtwarza adres instrukcji RETURN i skokiem do GOSLER wskazywany jest błąd (GOSub Line ERror).

6.3.5. Instrukcja FOR

    Instrukcja FOR rozpoczyna pętlę, w której wielokrotnie wykonywany jest zestaw innych instrukcji. Do realizacji tej instrukcji służy procedura XFOR.
            0100 ;eXecute FOR statement
            0110 ;
            0120 BMTUP = $B871
            0130 FR0 =   $D4
            0140 GETIX = $B904
            0150 LETVAR = $AC06
            0160 PHREG = $B888
            0170 PLSTK = $B823
            0180 SAVIX = $B883
            0190 SAVMHI = $C4
            0200 STMCUR = $8A
            0210 TMPIX = $B3
            0220 VARN =  $D3
            0230 XLET =  $AADA
            0240 ZFR0 =  $DA44
            0250 ;
            0260     *=  $B67D
            0270 ;
            0280     JSR SAVIX
            0290     JSR XLET
            0300     LDA VARN
            0310     ORA #$80
            0320     PHA
            0330     JSR PLSTK
            0340     LDA #$0C
            0350     JSR BMTUP
            0360     JSR LETVAR
            0370     LDX #FR0
            0380     LDY #$00
            0390     JSR PHREG
            0400     JSR ZFR0
            0410     LDA #$01
            0420     STA FR0+1
            0430     LDA #$40
            0440     STA FR0
            0450     JSR GETIX
            0460     BCS PHN
            0470     JSR LETVAR
            0480 PHN LDX #FR0
            0490     LDY #$06
            0500     JSR PHREG
            0510     PLA
            0520 ;
            0530 ;PusH on STacK
            0540 ;
            0550 PHSTK PHA
            0560     LDA #$04
            0570     JSR BMTUP
            0580     PLA
            0590     LDY #$00
            0600     STA (SAVMHI),Y
            0610     LDA (STMCUR),Y
            0620     INY
            0630     STA (SAVMHI),Y
            0640     LDA (STMCUR),Y
            0650     INY
            0660     STA (SAVMHI),Y
            0670     LDX TMPIX
            0680     DEX
            0690     TXA
            0700     INY
            0710     STA (SAVMHI),Y
            0720     RTS
    Rozpoczyna się ona od zapisania aktualnego stanu licznika INIX przez procedurę SAVIX oraz ustalenia przy pomocy procedury XLET stanu początkowego zmiennej sterującej (licznika pętli). Numer tej zmiennej jest odkładany na stos i wywoływana jest procedura PLSTK.
            0100 ;PulL from STacK
            0110 ;
            0120 ACNT2 = $C7
            0130 BMEMHI = $90
            0140 SAVMHI = $C4
            0150 SAVTST = $B87A
            0160 XPOP =  $B83E
            0170 ;
            0180     *=  $B823
            0190 ;
            0200     STA ACNT2
            0210     JSR SAVTST
            0220 POP JSR XPOP
            0230     BCS MEM
            0240     BEQ MEM
            0250     CMP ACNT2
            0260     BEQ END
            0270     BNE POP
            0280 MEM LDA SAVMHI
            0290     STA BMEMHI
            0300     LDA SAVMHI+1
            0310     STA BMEMHI+1
            0320 END RTS
    Zapisuje ona numer zmiennej do pomocniczego rejestru ACNT2 (Auxiliary CouNTer) oraz przepisuje aktualny wektor górnej granicy pamięci do rejestru SAVMHI (przy pomocy procedury SAVTST). Następnie przez kolejne wywołania XPOP przeszukiwany jest stos bieżący. Znalezienie danych dla procedury GOSUB lub osiągnięcie końca stosu przerywa to przeszukiwanie i powoduje odtworzenie wektora BMEMHI. Natomiast bez odtwarzania tego wektora procedura PLSTK kończy się w przypadku znalezienia na stosie zmiennej o tym samym numerze, co znajdujący się w rejestrze ACNT2.
            0100 ;SAVe Top of STack
            0110 ;
            0120 BMEMHI = $90
            0130 SAVMHI = $C4
            0140 ;
            0150     *=  $B87A
            0160 ;
            0170     LDX BMEMHI
            0180     STX SAVMHI
            0190     LDX BMEMHI+1
            0200     STX SAVMHI+1
            0210     RTS
    Teraz w akumulatorze umieszczona zostaje wartość $0C i wywoływana jest procedura BMTUP. Najpierw zapisuje ona aktualny stan BMEMHI, a potem podnosi go przy pomocy procedury INSEL o wartość z akumulatora, czyli o 12 bajtów, przez co uzyskuje się miejsce na umieszczenie parametrów zmiennej sterującej pętli (wartość początkowa, wartość końcowa i krok).
            0100 ;Basic Memory Top UP
            0110 ;
            0120 BMEMHI = $90
            0130 INSEL = $A87A
            0140 SAVTST = $B87A
            0150 ;
            0160     *=  $B871
            0170 ;
            0180     JSR SAVTST
            0190     TAY
            0200     LDX #BMEMHI
            0210     JMP INSEL
    Graniczna wartość licznika pętli jest ustalana przy pomocy procedury LETVAR. Przez kolejne wywołania XLET i GETVAR oblicza ona wartość tej granicy i przepisuje uzyskany wynik z bufora wejściowego do rejestru FR0.
            0100 ;LET VARiable
            0110 ;
            0120 GETVAR = $ABE9
            0130 XLET =  $AADA
            0140 ;
            0150     *=  $AC06
            0160 ;
            0170     JSR XLET
            0180     JMP GETVAR
    Obliczona wartość graniczna zmiennej sterującej jest przepisywana przez procedurę PHREG z rejestru FR0 do odpowiedniego miejsca stosu bieżącego. Używana jest w tym celu zawartość rejestru SAVMHI, gdyż w rejestrze BMEMHI znajduje się już nowy adres szczytu zajętej pamięci.
            0100 ;PusH REGister
            0110 ;
            0120 ACNT1 = $C6
            0130 SAVMHI = $C4
            0140 ;
            0150     *=  $B888
            0160 ;
            0170     LDA #$06
            0180     STA ACNT1
            0190 LOOP LDA $00,X
            0200     STA (SAVMHI),Y
            0210     INX
            0220     INY
            0230     DEC ACNT1
            0240     BNE LOOP
            0250     RTS
    Następnie w rejestrze FR0 umieszczana jest standardowa wartość kroku pętli (1). Jeśli procedura GETIX wskaże, że instrukcja FOR ma jeszcze dalszy ciąg, to liczba ta jest zastępowana przez wartość kroku odczytaną przez procedurę LETVAR. Kolejne wywołanie PHREG umieszcza odpowiednią wartość kroku pętli na stosie bieżącym.

    Na zakończenie przepisywane są na stos parametry instrukcji FOR. Są to kolejno: numer zmiennej użytej do sterowania pętli, numer wiersza zawierającego instrukcję FOR oraz indeks wskazujący początek instrukcji następującej po FOR. Ponieważ szczyt stosu jest przy tym ponownie podnoszony o cztery bajty, więc razem dla zapisania wszystkich informacji zostało wykorzystane 16 bajtów.

6.3.6. Instrukcja NEXT

    Instrukcja NEXT stanowi taką parę dla instrukcji FOR, jak RETURN dla GOSUB. Poza odtworzeniem adresu początkowego pętli trzeba tu jeszcze dokonać zmiany stanu licznika pętli i sprawdzić jego wartość. Do wykonania tych czynności służy procedura XNEXT. Jej początek jest podobny jak w procedurze XFOR. Tu jednak nieodnalezienie na stosie zmiennej o podanym numerze powoduje skok do procedury NFORER i zasygnalizowanie przez nią błędu (No matching FOR ERror).
            0100 ;eXecute NEXT statement
            0110 ;
            0120 ACNT2 = $C7
            0130 BADD =  $AD26
            0140 BMTUP = $B871
            0150 BRETLN = $BDC2
            0160 FR1 =   $E0
            0170 GETSUB = $AD20
            0180 INIX =  $A8
            0190 NFORER = $B91A
            0200 PLREG = $B897
            0210 RETURN = $BDCB
            0220 SAVVAL = $AC0C
            0230 STMCUR = $8A
            0240 VARBL = $AB81
            0250 XPOP =  $B83E
            0260 ;
            0270     *=  $B700
            0280 ;
            0290     LDY INIX
            0300     LDA (STMCUR),Y
            0310     STA ACNT2
            0320 POP JSR XPOP
            0330     BCS ERR
            0340     BEQ ERR
            0350     CMP ACNT2
            0360     BNE POP
            0370     LDY #$06
            0380     JSR PLREG
            0390     LDA FR1
            0400     PHA
            0410     LDA ACNT2
            0420     JSR VARBL
            0430     JSR BADD
            0440     JSR SAVVAL
            0450     LDY #$00
            0460     JSR PLREG
            0470     PLA
            0480     BPL BPS
            0490     JSR GETSUB
            0500     BPL EXIT
            0510     RTS
            0520 BPS JSR GETSUB
            0530     BEQ EXIT
            0540     BMI EXIT
            0550 END RTS
            0560 EXIT LDA #$10
            0570     JSR BMTUP
            0580     JSR RETURN
            0590     CMP #$08
            0600     BEQ END
            0610     JMP BRETLN
            0620 ERR JSR NFORER
    Po odnalezieniu parametrów właściwej instrukcji FOR wywoływana jest procedura PLREG (odwrotna do PHREG). Pobiera ona ze stosu wartość kroku i dodaje go do aktualnej wartości zmiennej sterującej, która została odczytana przez procedurę VARBL. Uzyskany rezultat jest ponownie zapisywany przy pomocy procedury SAVVAL.
            0100 ;PulL REGister
            0110 ;
            0120 ACNT1 = $C6
            0130 FR1 =   $E0
            0140 BMEMHI = $90
            0150 ;
            0160     *=  $B897
            0170 ;
            0180     LDA #$06
            0190     STA ACNT1
            0200     LDX #FR1
            0210 LOOP LDA (BMEMHI),Y
            0220     STA $00,X
            0230     INX
            0240     INY
            0250     DEC ACNT1
            0260     BNE LOOP
            0270     RTS
    Następne wywołanie PLREG powoduje odczytanie ze stosu granicznej wartości zmiennej sterującej. Warto przy tym zauważyć, że dla uproszczenia wartość odczytana przez PLREG jest zawsze umieszczana w rejestrze FR1. Po wykonaniu odejmowania przez procedurę GETSUB dalsze postępowanie zależy od znaku kroku pętli i znaku uzyskanego rezultatu. Jeśli została osiągnięta lub przekroczona graniczna wartość zmiennej sterującej, to procedura XNEXT kończy się rozkazem RTS i dalej wykonywana jest instrukcja następująca po NEXT. W przeciwnym wypadku przy użyciu procedury RETURN odczytywany jest adres pierwszej instrukcji pętli i tam przekazywane jest sterowanie.

6.3.7. Instrukcja IF

    Instrukcja IF umożliwia warunkowe wykonanie innych instrukcji, ewentualnie skoku, jeśli zamiast instrukcji umieszczony w niej będzie numer wiersza. Jej procedura realizacyjna - XIF - jest bardzo prosta.
            0100 ;eXecute IF statement
            0110 ;
            0120 BUFIX = $9F
            0130 FR0 =   $D4
            0140 GETIX = $B904
            0150 LETVAR = $AC06
            0160 OUTIX = $A7
            0170 XGOTO = $B6D5
            0180 ;
            0190     *=  $B778
            0200 ;
            0210     JSR LETVAR
            0220     LDA FR0+1
            0230     BEQ MIX
            0240     JSR GETIX
            0250     BCS END
            0260     JMP XGOTO
            0270 MIX LDA BUFIX
            0280     STA OUTIX
            0290 END RTS
    Przede wszystkim przez wywołanie procedury LETVAR obliczane jest wyrażenie warunkowe. Jeśli wynikiem jest zero, to po zrównaniu liczników BUFIX i OUTIX procedura się kończy. W takim przypadku wykonywanie programu jest kontynuowane od początku następnego wiersza. Jeśli wyrażenie warunkowe jest prawdziwe (wynik różny od zera), to procedura GETIX porównuje stany liczników bufora. Napotkanie końca wiersza powoduje skok do procedury XGOTO, a w przeciwnym wypadku wykonywane są dalsze instrukcje znajdujące się w tym samym wierszu.

6.3.8. Instrukcja ON

    Instrukcja ON jest wielokrotną warunkową instrukcją skoku i posiada dwie odmiany - ON/GOTO i ON/GOSUB. W zależności od wartości wyrażenia wykonywany jest skok do wiersza, którego numer jest umieszczony na odpowiedniej pozycji w instrukcji. Procedurą realizacyjną tej instrukcji jest XON.

    Rozpoczyna się ona odczytaniem wartości wyrażenia przy pomocy procedury GETBYT. Wynika z tego, że wyrażenie musi dawać wynik całkowity, mniejszy od 256, gdyż w innym przypadku wystąpi błąd. Zerowa wartość tego wyrażenia powoduje natychmiastowe opuszczenie procedury XON. Następnie sprawdzany jest rodzaj instrukcji ON. Jeśli jest to ON/GOSUB, to adres powrotny zapamiętywany jest przez wywołanie procedury SAVSTM.

    Teraz w pętli kolejno odczytywane są numery wierszy i zmniejszana jest obliczona wartość wyrażenia (przepisana do rejestru TMPIX). Wyzerowanie tego rejestru oznacza napotkanie właściwego numeru wiersza i powoduje wykonanie skoku przez przejście do środka procedury XGOSUB w miejsce oznaczone etykietą GOLINE. Jeśli wartość wyrażenia jest większa od liczby numerów wierszy zawartych w instrukcji ON, to procedura XON jest opuszczana bez wykonania skoku. W takim przypadku adres powrotny dla ON/GOSUB jest jeszcze zdejmowany ze stosu przez procedurę XPOP.
            0100 ;eXecute ON statement
            0110 ;
            0120 FR0 =   $D4
            0130 GETBYT = $ABE0
            0140 GETIX = $B904
            0150 GLNNUM = $ABCD
            0160 GOLINE = $B6D8
            0170 INIX =  $A8
            0180 SAVIX = $B883
            0190 SAVSTM = $B6F9
            0200 STMCUR = $8A
            0210 TMPIX = $B3
            0220 XPOP =  $B83E
            0230 ;
            0240     *=  $B7E4
            0250 ;
            0260     JSR SAVIX
            0270     JSR GETBYT
            0280     LDA FR0
            0290     BEQ END
            0300     LDY INIX
            0310     DEY
            0320     LDA (STMCUR),Y
            0330     CMP #$17
            0340     PHP
            0350     BEQ SKIP
            0360     JSR SAVSTM+3
            0370 SKIP LDA FR0
            0380     STA TMPIX
            0390 NEXT JSR GLNNUM
            0400     DEC TMPIX
            0410     BEQ JUMP
            0420     JSR GETIX
            0430     BCC NEXT
            0440     PLP
            0450     BEQ END
            0460     JSR XPOP
            0470 END RTS
            0480 JUMP PLP
            0490     JMP GOLINE

6.4. Obsługa komunikacji

    Wiele procedur interpretera komunikuje się z urządzeniami zewnętrznymi. Przeważnie są to procedury wykonawcze instrukcji wejścia/wyjścia, lecz nie tylko. Do realizacji tego celu przeznaczony jest zestaw procedur obsługujących komunikację z urządzeniami zewnętrznymi. Ze względu na wykorzystywanie przez liczne procedury realizujące instrukcje Basica zestaw ten został wydzielony w osobnym rozdziale.

    Podstawową procedurą komunikacji z urządzeniami zewnętrznymi jest PRPCHN. Przygotowuje i przeprowadza ona operacje wejścia/wyjścia, korzystając przy tym z innych procedur pomocniczych. Przed jej wywołaniem w rejestrze IOCHN (I/O CHannel Number) trzeba umieścić numer wykorzystywanego kanału IOCB, a w rejestrze IOCMD (I/O CoMmanD) kod rozkazu wykonywanej operacji. Ponadto, jeśli jest to operacja zapisu, w akumulatorze powinien znajdować się przesyłany znak. Przy wywoływaniu tej procedury od etykiety PRPDVC trzeba dodatkowo umieścić w rejestrze X numer kanału IOCB.
            0100 ENDIO = $BCBB
            0110 ICAX1 = $034A
            0120 ICAX1Z = $2A
            0130 ICAX2 = $034B
            0140 ICAX2Z = $2B
            0150 IOCAL = $BAB2
            0160 IOCHN = $B5
            0170 SAVDVC = $BAC0
            0180 ;
            0190     *=  $BA99
            0200 ;
            0210 ;PRePare CHaNnel
            0220 ;
            0230 PRPCHN LDX IOCHN
            0240 ;
            0250 ;PRePare DeViCe
            0260 ;
            0270 PRPDVC PHA
            0280     JSR SAVDVC
            0290     LDA ICAX1,X
            0300     STA ICAX1Z
            0310     LDA ICAX2,X
            0320     STA ICAX2Z
            0330     PLA
            0340     TAY
            0350     JSR IOCAL
            0360     TYA
            0370     JMP ENDIO+3
    Na początku, po odczytaniu numeru kanału z rejestru IOCHN i odłożeniu przesyłanego znaku na stosie, wywoływana jest procedura SAVDVC. Zapisuje ona numer kanału i przelicza go na postać wymaganą przez system operacyjny (zob. "Mapa pamięci Atari XL/XE. Procedury wejścia/wyjścia"), a wynik zwraca w rejestrze X. Następnie parametry transmisji z odpowiedniego bloku IOCB przepisywane są na stronę zerową. Teraz przesyłany znak jest zdejmowany ze stosu do rejestru Y i wywoływana jest procedura IOCAL.
            0100 ;Input/Output routine CAL1
            0110 ;
            0120 ICPUTB = $0346
            0130 ;
            0140     *=  $BAB2
            0150 ;
            0160     LDA ICPUTB+1,X
            0170     PHA
            0180     LDA ICPUTB,X
            0190     PHA
            0200     TYA
            0210     LDY #$92
            0220     RTS
    Jej zadaniem jest uruchomienie odpowiedniej procedury wykonującej operację I/O. W tym celu adres tej procedury jest przepisywany na stos, a przesyłany znak do akumulatora, zaś do rejestru Y zapisywany jest kod nieistniejącej operacji (Function Not Implemented). Wykonanie teraz rozkazu RTS powoduje zdjęcie ze stosu adresu procedury transmisji i tym samym wykonanie operacji. Po jej zakończeniu status operacji przepisywany jest z rejestru Y do akumulatora. Procedura PRPCHN kończy się skokiem do specjalnej procedury kończącej operacje wejścia/wyjścia - ENDIO.

    Wspomniana wcześniej procedura SAVDVC jest fragmentem nieco większej procedury SAVCMD. Umieszcza ona jedynie zawartość akumulatora w rejestrze IOCMD (tylko przy wywołaniu od SAVCMD) oraz zawartość rejestru X w IODVC (I/O DeViCe). Potem następuje bezpośredni skok do procedury MLTCHN.
            0100 IOCMD = $C0
            0110 IODVC = $C1
            0120 MLTCHN = $BCAF
            0130 ;
            0140     *=  $BABE
            0150 ;
            0160 ;SAVe CoMmanD
            0170 ;
            0180 SAVCMD STA IOCMD
            0190 ;
            0200 ;SAVe DeViCe number
            0210 ;
            0220 SAVDVC STX IODVC
            0230     JMP MLTCHN
    Także i ta procedura jest częścią większej - SETDVC. System operacyjny Atari wymaga, aby przy wywołaniu procedur I/O w rejestrze X znajdował się numer bloku IOCB pomnożony przez 16. Numer ten jest więc odczytywany z rejestru IODVC i przez czterokrotne przesunięcie w lewo doprowadzany do właściwej postaci. Zbyt duży numer kanału powoduje skok do DVCNER i sygnalizację błędu (DeViCe Number ERror).
            0100 DVCNER = $B90C
            0110 IODVC = $C1
            0120 IXGDAT = $BD07
            0130 ;
            0140     *=  $BCA8
            0150 ;
            0160 ;SET DeViCe
            0170 ;
            0180 SETDVC JSR IXGDAT
            0190     STA IODVC
            0200     BEQ ERR
            0210 ;
            0220 ;MuLTiple CHannel Number
            0230 ;
            0240 MLTCHN LDA IODVC
            0250     ASL A
            0260     ASL A
            0270     ASL A
            0280     ASL A
            0290     TAX
            0300     BPL $BD06   ;RTS
            0310 ERR JSR DVCNER
    Przy wywołaniu tej procedury od etykiety SETDVC ustalany jest najpierw numer kanału. W tym celu wywoływana jest procedura IXGDAT, która przy pomocy GLNNUM pobiera z bufora wejściowego liczbę. Liczba ta zostaje następnie umieszczona w rejestrze IODVC. Także tu niepoprawny (zerowy) numer kanału powoduje zasygnalizowanie błędu przez skok do DVCNER.
            0100 FR0 =   $D4
            0110 GLNNUM = $ABCD
            0120 INIX =  $A8
            0130 ;
            0140     *=  $BD07
            0150 ;
            0160 ;Increase indeX & Get DATa
            0170 ;
            0180 IXGDAT INC INIX
            0190 ;
            0200 ;GET DATa
            0210 ;
            0220 GETDAT JSR GLNNUM
            0230     LDA FR0
            0240     RTS
    Procedura kończąca operacje I/O służy do kontroli ich poprawnego wykonania i wstępnej obsługi ewentualnych błędów. W tym celu najpierw wywoływana jest procedura GETST, która odczytuje z odpowiedniego bloku IOCB status wykonanej operacji. Jeśli jest on mniejszy od $80, czyli przebieg operacji był poprawny, to procedura ENDIO kończy się rozkazem RTS (w tym przypadku znajduje się on w innej procedurze).
            0100 ;END I/O operation
            0110 ;
            0120 CDST =  $A000
            0130 CLCHN = $BCF7
            0140 DSPFLG = $02FE
            0150 ERRCOD = $B9
            0160 GETERR = $B934
            0170 GETST = $BD00
            0180 IODVC = $C1
            0190 IRQSTAT = $11
            0200 LOADFLG = $CA
            0210 PROMPT = $C2
            0220 RSTCHN = $BD5B
            0230 WRMST2 = $A053
            0240 ;
            0250     *=  $BCBB
            0260 ;
            0270     JSR GETST
            0280     BPL $BD06   ;RTS
            0290     LDY #$00
            0300     STY DSPFLG
            0310     CMP #$80
            0320     BNE GST
            0330     STY IRQSTAT
            0340     LDA LOADFLG
            0350     BEQ $BD06   ;RTS
            0360     JMP CDST
            0370 GST LDY IODVC
            0380     CMP #$88
            0390     BEQ EXIT
            0400 PST STA ERRCOD
            0410     CPX #$07
            0420     BNE RST
            0430     JSR CLCHN
            0440 RST JSR RSTCHN
            0450     JMP GETERR
            0460 EXIT CPX #$07
            0470     BNE PST
            0480     LDX #$5D
            0490     CPX PROMPT
            0500     BNE PST
            0510     JSR CLCHN
            0520     JMP WRMST2

            0100 ;GET STatus
            0110 ;
            0120 ICSTAT = $0343
            0130 MLTCHN = $BCAF
            0140 ;
            0150     *=  $BD00
            0160 ;
            0170     JSR MLTCHN
            0180     LDA ICSTAT,X
            0190     RTS
    Jeśli status wskazuje niepoprawny przebieg operacji, to po wyzerowaniu znacznika DSPFLG (DiSPlay FLaG) jest on porównywany z kodem przerwania przez naciśnięcie klawisza BREAK ($80). Taka przyczyna błędu jest zapisywana w rejestrze IRQSTAT (IRQ STATus shadow register). Jeżeli operacja I/O dotyczyła odczytu programu z pamięci masowej, co wskazuje niezerowa zawartość rejestru LOADFLG (LOADing FLaG), to następuje ponowne zainicjowanie interpretera przez skok do CDST. W przeciwnym przypadku procedura ENDIO kończy się rozkazem RTS.

    Następnie sprawdzane jest, czy status sygnalizuje napotkanie końca pliku ($88). Jeśli tak, to w przypadku odczytu programu zamykany jest kanał 7 (poprzez CLCHN) i wykonywany jest skok do gorącego startu, a więc interpreter przechodzi do trybu bezpośredniego bez sygnalizowania błędu. Każdy inny status błędu powoduje zamknięcie kanału (z wyjątkiem kanału IOCB 0), ustawienie wyjścia na kanał 0 (przez procedurę RSTCHN) i sygnalizowanie błędu przez skok do procedury GETERR (zob. rozdział 3).

    Zamknięcie kanału IOCB jest wykonywane przez procedurę CLCHN. Ponieważ numer kanału jest ustalany przez procedurę MLTCHN, to zawsze zamykany jest kanał o numerze zapisanym w rejestrze IODVC. Kanał IOCB 0 jest wykorzystywany przez edytor ekranowy i jego zamknięcie jest niemożliwe. Zerowy numer kanału powoduje więc przerwanie procedury rozkazem RTS. W przeciwnym przypadku do akumulatora wpisywany jest kod operacji CLOSE ($0C) i następuje skok do procedury CIOEXE.
            0100 ;CLose CHaNnel
            0110 ;
            0120 CIOEXE = $BD2B
            0130 MLTCHN = $BCAF
            0140 ;
            0150     *=  $BCF7
            0160 ;
            0170     JSR MLTCHN
            0180     BEQ $BD06   ;RTS
            0190     LDA #$0C
            0200     BNE CIOEXE
    Etykieta CIOEXE oznacza końcowy fragment procedury BFLN. Rozpoczyna się ona od ustalenia długości bufora wykorzystywanego podczas operacji I/O. Długość tego bufora jest zależna od miejsca rozpoczęcia procedury. Przy wywołaniu od BFLN1 długość bufora wynosi $FF, od BFLN2 - zero (znak przesyłany jest więc w akumulatorze), od BFLN3 - długość przepisywana jest z rejestru Y (mniejsza od $0100), zaś przy wywołaniu od BFLN4 długość ustalana jest według zawartości akumulatora (starszy bajt) i rejestru Y (młodszy bajt).

    Teraz (od etykiety SIBUFA) jako adres bufora jest przepisywany wektor zawarty w rejestrze INBUFP (INput BUFfer Pointer). Następnie z rejestru IOCMD odczytywany jest do akumulatora kod rozkazu operacji, która ma być wykonana (etykieta CMDEXE). Kod ten jest umieszczany w rejestrze ICCMND (IOCB CoMmaND register) odpowiedniego bloku IOCB. To miejsce jest właśnie oznaczone etykietą CIOEXE. Cała procedura kończy się bezpośrednim skokiem do centralnej procedury wejścia/wyjścia systemu operacyjnego - CIOMAIN (zob. "Mapa pamięci Atari XL/XE. Procedury wejścia/wyjścia.").
            0100 ICBUFA = $0344
            0110 ICBUFL = $0348
            0120 ICCMND = $0342
            0130 INBUFP = $F3
            0140 IOCMD = $C0
            0150 JCIOMAIN = $E456
            0160 ;
            0170     *=  $BD0F
            0180 ;
            0190 ;set BuFfer LeNgth
            0200 ;
            0210 BFLN1 LDY #$FF
            0220     BNE BFLN3
            0230 BFLN2 LDY #$00
            0240 BFLN3 LDA #$00
            0250 BFLN4 STA ICBUFL+1,X
            0260     TYA
            0270     STA ICBUFL,X
            0280 ;
            0290 ;Set Input BUFfer Address
            0300 ;
            0310 SIBUFA LDA INBUFP+1
            0320     LDY INBUFP
            0330     STA INBUFA+1,X
            0340     TYA
            0350     STA ICBUFA,X
            0360 ;
            0370 ;CoMmanD EXEcute
            0380 ;
            0390 CMDEXE LDA IOCMD
            0400 ;
            0410 ;Central I/O EXEcute
            0420 ;
            0430 CIOEXE STA ICCMND,X
            0440     JMP JCIOMAIN

6.5. Instrukcje dźwiękowe i graficzne

    W grupie instrukcji wejścia/wyjścia najczęściej używane są instrukcje dźwiękowe i graficzne. Dlatego też zostały one wydzielone w osobnym rozdziale. Są to instrukcje: SOUND, SETCOLOR, COLOR, POSITION, PLOT, DRAWTO i GRAPHICS. Istnieją jeszcze inne instrukcje działające na ekranie, lecz ze względu na ich wykorzystanie przy współpracy z urządzeniami zewnętrznymi znajdują się one w następnym rozdziale.

6.5.1. Instrukcja SOUND

    Instrukcja SOUND powoduje uruchomienie wskazanego generatora dźwięku. Praca generatora trwa do następnej przeznaczonej dla niego instrukcji SOUND albo do instrukcji NEW, END lub RUN. Instrukcja SOUND wymaga czterech parametrów, które oznaczają kolejno: numer generatora, okres generatora, rodzaj zniekształceń i głośność dźwięku. Do realizacji tej instrukcji służy procedura XSOUND.
            0100 ;eXecute SOUND statement
            0110 ;
            0120 AUDC1 = $D201
            0130 AUDCTL = $D208
            0140 AUDF1 = $D200
            0150 FR0 =   $D4
            0160 GETBYT = $ABE0
            0170 LETNUM = $ABD7
            0180 SKCTL = $D20F
            0190 ;
            0200     *=  $B9D3
            0210 ;
            0220     JSR GETBYT
            0230     LDA FR0
            0240     CMP #$04
            0250     BCS $B9D0   ;JMP BVALER
            0260     ASL A
            0270     PHA
            0280     LDA #$00
            0290     STA AUDCTL
            0300     LDA #$03
            0310     STA SKCTL
            0320     JSR LETNUM
            0330     PLA
            0340     PHA
            0350     TAX
            0360     LDA FR0
            0370     STA AUDF1,X
            0380     JSR LETNUM
            0390     LDA FR0
            0400     ASL A
            0410     ASL A
            0420     ASL A
            0430     ASL A
            0440     PHA
            0450     JSR LETNUM
            0460     PLA
            0470     TAY
            0480     PLA
            0490     TAX
            0500     TYA
            0510     CLC
            0520     ADC FR0
            0530     STA AUDC1,X
            0540     RTS
    Jako pierwszy pobierany jest przez procedurę GETNUM numer generatora. Jeśli jest on większy od 3, to procedura jest przerywana skokiem do BVALER, gdzie sygnalizowany jest błąd. Poprawna wartość jest mnożona przez dwa i odkładana na stosie. Następnie ustawiane są początkowe stany rejestrów AUDCTL (AUDio ConTroL) oraz SKCTL (Serial/Keyboard ConTroL). Wywołana teraz procedura LETNUM odczytuje wartość okresu generatora, która jest wpisywana przy użyciu odtworzonego ze stosu numeru do rejestru AUDF (AUDio Frequerency) odpowiedniego generatora. Kolejne wywołanie LETNUM pobiera kod zniekształceń dźwięku. Jest on mnożony przez 16 i odkładany na stos. Trzecie i ostatnie wywołanie LETNUM daje wartość głośności dźwięku. Do tej wartości dodawany jest zdjęty ze stosu kod zniekształceń - cztery młodsze bity określają więc głośność, a cztery starsze zniekształcenie. Wynik umieszczany jest w rejestrze AUDC (AUDio Control) odpowiedniego generatora.

6.5.2. Instrukcja SETCOLOR

    Zadaniem instrukcji SETCOLOR jest ustawienie barwy i jasności koloru w jednym z rejestrów koloru obrazu. Do tego celu potrzebne są trzy parametry: numer rejestru koloru oraz barwa i jasność koloru. Procedura realizacyjna tej instrukcji - XSETC - jest bardzo podobna do procedury XSOUND.
            0100 ;eXecute SETCOLOR statement
            0110 ;
            0120 BVALER = $B92E
            0130 COLFP0S = $02C4
            0140 FR0 =   $D4
            0150 GETBYT = $ABE0
            0160 LETNUM = $ABD7
            0170 ;
            0180     *=  $B9AD
            0190 ;
            0200     JSR GETBYT
            0210     LDA FR0
            0220     CMP #$05
            0230     BCS ERR
            0240     PHA
            0250     JSR LETNUM
            0260     LDA FR0
            0270     ASL A
            0280     ASL A
            0290     ASL A
            0300     ASL A
            0310     PHA
            0320     JSR LETNUM
            0330     PLA
            0340     CLC
            0350     ADC FR0
            0360     TAY
            0370     PLA
            0380     TAX
            0390     TYA
            0400     STA COLPF0S,X
            0410     RTS
            0420 ERR JSR BVALER
    Rozpoczyna się ona również od pobrania przez GETBYT numeru rejestru, sprawdzenia jego wartości i odłożenia jej na stos. Następnie przez dwukrotne wywołanie LETNUM odczytywane są dwa pozostałe parametry. Są one sumowane podobnie jak w procedurze XSOUND - kod barwy zajmuje cztery starsze bity, a kod jasności cztery młodsze. Uzyskany wynik jest zapisywany według numeru pobranego ze stosu do odpowiedniego rejestru koloru obrazu COLPF (COLor of Play Field - rejestry 0-3) lub tła COLBAK (COLor of BAcKground - rejestr 4).

6.5.3. Instrukcja COLOR

    Instrukcja COLOR ustala numer rejestru koloru lub kod znaku dla następnych instrukcji graficznych. Numer koloru jest jednak inny niż użyty w instrukcji SETCOLOR. Rejestrom 0-3 odpowiadają tu bowiem numery 1-4, zaś rejestrowi 4 (tło) numer 0 (poza trybami graficznymi 9, 10 i 11, które są sterowane przez GTIA). Instrukcja COLOR jest realizowana przez procedurę XCOLOR. Pobiera ona przy pomocy procedury LETNUM liczbę i zapisuje ją do rejestru COLOR, z którego korzystają inne procedury graficzne. Wartość tej liczby nie jest tu sprawdzana i może mieć dowolną wartość mniejszą od $FFFF (większe wartości spowodują błąd w procedurze LETNUM). Zapisywany jest jednak tylko młodszy bajt kodu, więc w rezultacie maksymalny numer koloru lub kod znaku wynosi $FF.
            0100 ;eXecute COLOR statement
            0110 ;
            0120 COLOR = $C8
            0130 FR0 =   $D4
            0140 LETNUM = $ABD7
            0150 ;
            0160     *=  $BA1F
            0170 ;
            0180     JSR LETNUM
            0190     LDA FR0
            0200     STA COLOR
            0210     RTS

6.5.4. Instrukcja POSITION

    Instrukcja POSITION umieszcza kursor na podanej pozycji. Jest ona realizowana przez procedurę XPOS. Najpierw pozioma pozycja kursora odczytywana jest przy pomocy LETNUM i jej oba bajty przepisywane są do rejestru COLCRS (COLumn of CuRSor). Następnie wywoływana jest procedura GETBYT odczytująca pozycję pionową, która przepisywana jest do rejestru ROWCRS (ROW of CuRSor). Odczyt współrzędnych jest wykonywany przez różne procedury, gdyż maksymalna pozycja pozioma wynosi 319 (liczba dwubajtowa), zaś maksymalna pozycja pionowa 191, a więc jeden bajt.
            0100 ;eXecute POSITION statement
            0110 ;
            0120 COLCRS = $55
            0130 FR0 =   $D4
            0140 GETBYT = $ABE0
            0150 LETNUM = $ABD7
            0160 ROWCRS = $54
            0170 ;
            0180     *=  $BA0C
            0190 ;
            0200     JSR LETNUM
            0210     LDA FR0
            0220     STA COLCRS
            0230     LDA FR0+1
            0240     STA COLCRS+1
            0250     JSR GETBYT
            0260     LDA FR0
            0270     STA ROWCRS
            0280     RTS

6.5.5. Instrukcja PLOT

    Instrukcja PLOT umieszcza znak (w trybie tekstowym) lub punkt (w trybie bitowym) we wskazanym miejscu ekranu. Numer koloru lub kod znaku pobierany jest przy tym z rejestru COLOR. Operację tą wykonuje procedura XPLOT. Najpierw przez wywołanie procedury XPOS kursor ustawiany jest na odpowiedniej pozycji. Następnie do akumulatora pobierany jest numer koloru lub kod znaku, a do rejestru X numer IOCB 6, który służy do przeprowadzania operacji graficznych. Potem wykonywany jest skok do procedury PRPDVC, która przygotowuje i przeprowadza (przy pomocy procedur systemu operacyjnego) operację zapisu punktu lub znaku na ekranie.
            0100 ;eXecute PLOT statement
            0110 ;
            0120 COLOR = $C8
            0130 PRPDVC = $BA9B
            0140 XPOS =  $BA0C
            0150 ;
            0160     *=  $BA6C
            0170 ;
            0180     JSR XPOS
            0190     LDA COLOR
            0200     LDX #$06
            0210     JMP PRPDVC

6.5.6. Instrukcja DRAWTO

    Instrukcja DRAWTO rysuje linię od aktualnej pozycji kursora do pozycji o podanych współrzędnych. Procedura realizacyjna XDRAW rozpoczyna się, podobnie jak XPLOT, od wywołania XPOS i odczytania kodu znaku lub numeru koloru. Ta ostatnia wartość jest teraz przepisywana do rejestru ATACHR (ATASCII CHaRacter). Następnie w akumulatorze umieszczany jest kod operacji rysowania linii ($11), a w rejestrze X numer kanału IOCB ($06). Wartości te są doprowadzane do właściwej postaci i zapisywane do odpowiednich rejestrów RAM przez wywołanie procedury SAVCMD. Po ustawieniu parametrów pomocniczych w rejestrach ICAX1 i ICAX2 (IOCB AuXiliary register) operacja jest wykonywana przez wywołanie procedury CMDEXE. Po jej przeprowadzeniu XDRAW kończy się skokiem do ENDIO, gdzie kontrolowany jest jeszcze status wykonanej operacji.
            0100 ;eXecute DRAWTO statement
            0110 ;
            0120 ATACHR = $02FB
            0130 CMDEXE = $BD29
            0140 COLOR = $C8
            0150 ENDIO = $BCBB
            0160 ICAX1 = $034A
            0170 ICAX2 = $034B
            0180 SAVCMD = $BABE
            0190 XPOS =  $BA0C
            0200 ;
            0210     *=  $BA27
            0220 ;
            0230     JSR XPOS
            0240     LDA COLOR
            0250     STA ATACHR
            0260     LDA #$11
            0270     LDX #$06
            0280     JSR SAVCMD
            0290     LDA #$0C
            0300     STA ICAX1,X
            0310     LDA #$00
            0320     STA ICAX2,X
            0330     JSR CMDEXE
            0340     JMP ENDIO

6.5.7. Instrukcja GRAPHICS

    Instrukcja GRAPHICS służy do wyboru trybu graficznego. Polega to na otwarciu kanału IOCB dla ekranu (Screen) i jest wykonywane przez instrukcję XGRAPH. Wszystkie operacje na ekranie są standardowo wykonywane poprzez kanał szósty, więc najpierw do rejestru IODVC wpisywany jest numer tego kanału i wywoływana jest procedura CLCHN, która go zamyka. Następnie wymagany numer trybu graficznego jest odczytywany przez procedurę LETNUM, a adres nazwy urządzenia SCRNAM jest przepisywany do wektora bufora INBUFP. Teraz numer trybu jest pobierany z rejestru FR0 i umieszczany w akumulatorze, a jego bity 4-7 w rejestrze Y (określają one rodzaj otwarcia urządzenia). Sama operacja otwarcia przeprowadzana jest przez procedurę PRPOPN, a kontrola statusu tej operacji przez ENDIO.
            0100 ;eXecute GRAPHICS statement
            0110 ;
            0120 CLCHN = $BCF7
            0130 ENDIO = $BCBB
            0140 FR0 =   $D4
            0150 INBUFP = $F3
            0160 IODVC = $C1
            0170 LETNUM = $ABD7
            0180 PRPOPN = $BBD8
            0190 ;
            0200     *=  $BA46
            0210 ;
            0220     LDX #$06
            0230     STX IODVC
            0240     JSR CLCHN
            0250     JSR LETNUM
            0260     LDX # <SCRNAM
            0270     LDY # >SCRNAM
            0280     STX INBUFP
            0290     STY INBUFP+1
            0300     LDX #$06
            0310     LDA FR0
            0320     AND #$F0
            0330     EOR #$1C
            0340     TAY
            0350     LDA FR0
            0360     JSR PRPOPN
            0370     JMP ENDIO
            0380 ;
            0390 SCRNAM .BYTE "S:",$9B
    Procedura PRPOPN ustala kod wykonywanej operacji na $03 (OPEN) i zapisuje go do odpowiednich rejestrów przy pomocy SAVCMD. Następnie umieszcza przekazane parametry otwarcia ekranu w rejestrach ICAX1 i ICAX2. Wywołanie systemowej procedury I/O, która otwiera ekran, odbywa się za pośrednictwem SIBUFA (dodatkowo ustala ona adres bufora). Procedura PRPOPN kończy się bezpośrednim skokiem do STBV, gdzie odtwarzana jest poprzednia wartość wektora INBUFP.
            0100 ;PRePare for OPeN
            0110 ;
            0120 ICAX1 = $034A
            0130 ICAX2 = $034B
            0140 SAVCMD = $BABE
            0150 SIBUFA = $BD1E
            0160 STBV =  $DA51
            0170 ;
            0180     *=  $BBD8
            0190 ;
            0200     PHA
            0210     LDA #$03
            0220     JSR SAVCMD
            0230     PLA
            0240     STA ICAX2,X
            0250     TYA
            0260     STA ICAX1,X
            0270     JSR SIBUFA
            0280     JMP STBV

6.6. Instrukcje wejścia/wyjścia

    Ostatnią, najliczniejszą grupę instrukcji Atari Basic stanowią instrukcje wejścia/wyjścia. Służą one do komunikacji komputera z urządzeniami zewnętrznymi, w tym także z edytorem i ekranem. Są to następujące instrukcje: CLOSE, OPEN, XIO, STATUS, PUT, GET, LOCATE, PRINT, LPRINT, POINT, NOTE, INPUT, READ, SAVE, CSAVE, LOAD, CLOAD, ENTER i LIST.

6.6.1. Instrukcja CLOSE

    Instrukcja CLOSE zamyka podany kanał wejścia/wyjścia, a więc służy do zakończenia komunikacji przez odpowiedni blok IOCB (zob. "Mapa pamięci Atari XL/XE. Procedury wejścia/wyjścia."). Jest ona realizowana przez procedurę wykonawczą XCLOSE.
            0100 CMDEXE = $BD2B
            0110 ENDIO = $BCBB
            0120 IOCMD = $C0
            0130 SETDVC = $BCA8
            0140 ;
            0150     *=  $BC22
            0160 ;
            0170 ;eXecute CLOSE statement
            0180 ;
            0190 XCLOSE LDA #$0C
            0200 ;
            0210 ;PRoCeed I/O
            0220 ;
            0230 PRCIO STA IOCMD
            0240     JSR SETDVC
            0250 ;
            0260 ;I/O OPERation
            0270 ;
            0280 IOOPER JSR CMDEXE
            0290     JMP ENDIO
    Procedura ta umieszcza w rejestrze IOCMD (I/O CoMmanD) kod operacji zamknięcia kanału, a następnie przez wywołanie SETDVC ustala numer kanału według wartości odczytanej z bufora wejściowego. Operacja jest realizowana przez wywołanie procedury CMDEXE, a sprawdzenie statusu i obsługę ewentualnego błędu wykonuje procedura ENDIO.

    Dwie dodatkowe etykiety - PRCIO i IOOPER - pozwalają na wykorzystanie tej procedury do innych operacji I/O. Po wywołaniu od PRCIO na kanale, którego numer zawiera rejestr X, wykonywana jest operacja, której kod umieszczony jest w akumulatorze. Realizacja operacji I/O, której parametry zostały już wcześniej ustalone, następuje po wywołaniu procedury od etykiety IOOPER.

6.6.2. Instrukcje XIO i OPEN

    Instrukcja XIO jest uniwersalną instrukcją wejścia/wyjścia i służy do wykonania dowolnej operacji, której kod zostanie podany jako pierwszy parametr. Kolejnymi parametrami są: numer kanału, dwa parametry pomocnicze i nazwa pliku lub urządzenia. Instrukcja OPEN dokonuje otwarcia kanału IOCB do komunikacji z urządzeniem zewnętrznym. Jej składnia jest taka sama jak instrukcji XIO, z wyjątkiem pierwszego parametru (numer kanału, dwa parametry pomocnicze i nazwa pliku lub urządzenia).

    Procedury wykonawcze tych instrukcji - XXIO i XOPEN - mają wspólny przebieg, a różnią się jedynie etapem początkowym. XXIO rozpoczyna się od wywołania procedury GETDAT, która odczytuje kod operacji do wykonania. Na początku procedury XOPEN kod ten jest ustalany na $03 (OPEN). Teraz - od zapisania kodu w rejestrze IOCMD - obie procedury przebiegają wspólnie. Następnie procedura SETDVC odczytuje z bufora numer wykorzystywanego kanału IOCB. Dwie dalsze wartości (parametry pomocnicze) są odczytywane przez kolejne wywołania procedury GETDAT i umieszczane w akumulatorze (pierwszy parametr) i rejestrze Y (drugi parametr). Warto przy tym zwrócić uwagę, że zarówno procedura SETDVC, jak i GETDAT przyjmują bez sygnalizowania błędu dane dwubajtowe, lecz uwzględniany jest tylko młodszy bajt danej.
            0100 BFLN1 = $BD0F
            0110 ENDIO = $BCBB
            0120 GETDAT = $BD09
            0130 GFILSP = $BD7D
            0140 ICAX1 = $034A
            0150 ICAX2 = $034B
            0160 IOCMD = $C0
            0170 MLTCHN = $BCAF
            0180 PSTMAD = $BD9D
            0190 SETDVC = $BCA8
            0200 STBV =  $DA51
            0210 CLET =  $AADA
            0220 ;
            0230     *=  $BBEC
            0240 ;
            0250 ;eXecute XIO statement
            0260 ;
            0270 XXIO JSR GETDAT
            0280     JMP EXE
            0290 ;
            0300 ;eXecute OPEN statement
            0310 ;
            0320 XOPEN LDA #$03
            0330 EXE STA IOCMD
            0340     JSR SETDVC
            0350     JSR GETDAT
            0360     PHA
            0370     JSR GETDAT
            0380     TAY
            0390     PLA
            0400 ;
            0410 ;OPeN CHaNnel
            0420 ;
            0430 OPNCHN PHA
            0440     TYA
            0450     PHA
            0460     JSR XLET
            0470     JSR GFILSP
            0480     JSR MLTCHN
            0490     PLA
            0500     STA ICAX2,X
            0510     PLA
            0520     STA ICAX1,X
            0530     JSR BFLN1
            0540     JSR PSTMAD
            0550     JSR STBV
            0560     JMP ENDIO
    Realizacja operacji I/O rozpoczyna się od etykiety OPNCHN. Najpierw wartości przekazane w akumulatorze i rejestrze Y są odkładane na stosie i wywoływana jest procedura XLET. Według obliczonego przez nią adresu procedura GFILSP odczytuje specyfikację pliku lub urządzenia. Następnie poprzez MLTCHN obliczany jest poprawny numer bloku IOCB i zdjęte ze stosu parametry dodatkowe przepisywane są do rejestrów ICAX1 i ICAX2. Ustalenie pozostałych parametrów i wykonanie operacji jest przeprowadzane bezpośrednio przez procedurę BFLN. Przed kończącym procedurę skokiem do ENDIO odtwarzany jest jeszcze przy pomocy STBV wektor bufora wejściowego.

6.6.3. Instrukcja STATUS

    Instrukcja STATUS odczytuje status podanego urządzenia lub pliku, a jego wartość przypisuje wskazanej zmiennej. Jej procedurą wykonawczą jest XSTAT.
            0100 ;eXecute STATUS statement
            0110 ;
            0120 CIOEXE = $BD2B
            0130 GETST = $BD00
            0140 SAVBYT = $BD31
            0150 SETDVC = $BCA8
            0160 ;
            0170     *=  $BC2F
            0180 ;
            0190     JSR SETDVC
            0200     LDA #$0D
            0210     JSR CIOEXE
            0220     JSR GETST
            0230     JMP SAVBYT
    Po odczytaniu przez procedurę SETDVC numeru kanału, do akumulatora wpisywany jest kod operacji STATUS ($0D). Operacja jest realizowana przez wywołanie procedury CIOEXE, a jej status odczytuje procedura GETST. Uzyskany wynik jest zapisywany przy pomocy procedury SAVBYT.

    Najpierw odkłada ona na stosie przekazaną w akumulatorze wartość (a przy wywołaniu od etykiety SAVWRD także wartość z rejestu Y). Następnie przez wywołanie procedury LETVAR odczytywana jest wskazana zmienna. Zdjęte ze stosu wartości wpisywane są do jej dwóch pierwszych bajtów i przez wywołanie procedury IFP zamieniane na liczbę zmiennoprzecinkową. Procedura XSTAT kończy się skokiem do SAVVAL, gdzie uzyskana liczba jest przepisywana do tablicy wartości zmiennych.
            0100 FR0 =   $D4
            0110 IFP =   $D9AA
            0120 LETVAR = $AC06
            0130 SAVVAL = $AC0C
            0140 ;
            0150     *=  $BD31
            0160 ;
            0170 ;SAVe BYTe
            0180 ;
            0190 SAVBYT LDY #$00
            0200 ;
            0210 ;SAVe WoRD
            0220 ;
            0230 SAVWRD PHA
            0240     TYA
            0250     PHA
            0260     JSR LETVAR
            0270     PLA
            0280     STA FR0+1
            0290     PLA
            0300     STA FR0
            0310     JSR IFP
            0320     JMP SAVVAL

6.6.4. Instrukcja PUT

    Zadaniem instrukcji PUT jest zapisanie we wskazanym kanale IOCB podanej wartości. Czynność tą wykonuje procedura XPUT, która rozpoczyna się od ustalenia przy pomocy SETDVC odpowiedniego numeru kanału.
            0100 ;eXecute PUT statement
            0110 ;
            0120 FR0 =   $D4
            0130 IODVC = $C1
            0140 LETNUM = $ABD7
            0150 PRPDVC = $BA9B
            0160 SETDVC = $BCA8
            0170 ;
            0180     *=  $BC78
            0190 ;
            0200     JSR SETDVC
            0210     JSR LETNUM
            0220     LDA FR0
            0230     LDX IODVC
            0240     JMP PRPDVC
    Następnie w akumulatorze umieszczany jest odczytany przez procedurę LETNUM bajt do zapisu, zaś w rejestrze X numer kanału pobrany z IODVC (I/O DeViCe). Procedura XPUT kończy się bezpośrednim skokiem do PRPDVC, gdzie dokonuje się realizacja zapisu i kontrola statusu tej operacji.

6.6.5. Instrukcje GET i LOCATE

    Zadaniem instrukcji GET jest odczytanie ze wskazanego kanału IOCB wartości i przypisanie jej podanej zmiennej. Instrukcja LOCATE wykonuje podobne zadanie, lecz odczyt następuje zawsze z ekranu i z podanej pozycji kursora. Procedury wykonawcze tych instrukcji - XGET i XLOCAT - są więc również podobne.
            0100 BFLN3 = $BD15
            0110 ENDIO = $BCBB
            0120 INBUFP = $F3
            0130 IOCMD = $C0
            0140 SAVBYT = $BD31
            0150 SAVDVC = $BCA8
            0160 STBV =  $DA51
            0170 XPOS =  $BA0C
            0180 ;
            0190     *=  $BC85
            0200 ;
            0210 ;eXecute GET statement
            0220 ;
            0230 XGET JSR STBV
            0240     JSR SETDVC
            0250 EXE LDA #$07
            0260     STA IOCMD
            0270     LDY #$01
            0280     JSR BFLN3
            0290     JSR ENDIO
            0300     LDY #$00
            0310     LDA (INBUFP),Y
            0320     JMP SAVBYT
            0330 ;
            0340 ;eXecute LOCATE statement
            0350 ;
            0360 XLOCAT JSR XPOS
            0370     LDX #$06
            0380     JSR SAVDVC
            0390     BNE EXE
    Procedura XGET na początku ustawia przy pomocy STBV adres bufora dla operacji I/O oraz numer kanału IOCB (przez wywołanie SETDVC). Natomiast procedura XLOCAT najpierw przez wywołanie XPOS umieszcza kursor na odpowiedniej pozycji ekranu, a następnie przy pomocy SAVDVC ustala numer kanału na 6. Dalej obie procedury przebiegają identycznie. Do rejestru IOCMD wpisywany jest kod operacji GET BYTE ($07), a procedura BFLN ustala długość bufora na jeden znak. Po sprawdzeniu poprawności operacji przy pomocy ENDIO odczytana liczba jest umieszczana w akumulatorze. Procedury XGET i XLOCAT są opuszczane skokiem do SAVBYT, która przypisuje otrzymaną wartość wskazanej zmiennej.

6.6.6. Instrukcja PRINT

    Instrukcja PRINT służy do zapisywania dowolnych wartości na urządzeniu zewnętrznym. Numer tego urządzenia powinien być podany jako pierwszy parametr i oznaczony znakiem "#". W przypadku braku numeru urządzenia interpreter przyjmuje, że zapis ma być dokonany do kanału IOCB o numerze 0 czyli do edytora. W instrukcji PRINT poza wartościami mogą znajdować się separatory, które służą do nadania odpowiedniej formy zapisywanej informacji. Separatorami typi są: średnik (;), przecinek (,), dwukropek (:) i znak końca wiersza (EOL - End Of Line). Procedura wykonawcza XPRINT, która realizuje tą instrukcję, rozpoznaje kolejno w pętli elementy (wartości i separatory) oraz realizuje ich zapis. Przed rozpoczęciem pętli skok tabulacji (liczba znaków między sąsiednimi pozycjami tabulacji) jest przepisywany z rejestru PTABW (Position TABulate Width) do AUXBR, a licznik wyjściowy COX (Current Output indeX) jest zerowany.

    Pierwszą czynnością w każdym przejściu pętli jest odczyt tokena do zapisu i jego rozpoznanie. Jeśli nie jest to token żadnego separatora, to wywoływane są procedury XLET i GETVAR, które kolejno obliczają wartość do zapisu i pobierają ją z bufora wejściowego. Rodzaj wartości (liczbowa czy tekstowa) jest rozpoznawany według najstarszego bitu rejestru VART.

    Wartości liczbowe są najpierw doprowadzane do standardowego formatu, w którym przedstawiane jest dziewięć cyfr znaczących. Po zamianie tej liczby na ciąg znaków ASCII (przez procedurę FASC) kolejne znaki są odczytywane z bufora i zapisywane przy pomocy procedury RSTHIB (zob. niżej). Ostatni znak liczby jest sygnalizowany przez ustawienie w nim najstarszego bitu. Po jego zapisaniu następuje skok do początku głównej pętli (PRNT).

    Przed zapisem wartości tekstowej wywoływana jest procedura FTARV, która odczytuje parametry ciągu. Następnie kolejne znaki ciągu są zapisywane przez procedurę INOUTX. Jako licznik znaków służą w tym przypadku trzeci i czwarty bajt informacji o ciągu, które zawierają jego aktualną długość. Po zapisaniu całego żądanego tekstu następuje powrót do pętli głównej.

    Rozpoznanie tokena numeru kanału ($1C) powoduje wywołanie procedury IXGDAT. Odczytany przez nią numer IOCB jest przepisywany do rejestru IOCHN i procedura XPRINT przechodzi do rozpoznawania następnego tokena.

    Średnik (;) powoduje zapisanie następnej wartości bezpośrednio po ostatnio zapisanej. Po odczytaniu jego tokena ($15) sprawdzany jest następny token. Jeżeli jest to znak inny niż dwukropek (:) lub koniec wiersza (znak RETURN), to powtarzana jest główna pętla procedury. W przeciwnym przypadku zerowany jest rejestr IOCHN (odtwarza to standardowe urządzenie wyjścia - edytor) i procedura XPRINT się kończy.

    W każdym innym - niż opisany powyżej - przypadku rozpoznanie tokena kończącego instrukcję PRINT (dwukropek - $14 lub koniec wiersza - $16) powoduje wywołanie procedury INOUTX (wewnątrz RSTHIB), która zapisuje znak RETURN ($9B). Po wyzerowaniu rejestru IOCHN procedura XPRINT także się kończy.
            0100 ;eXecute PRINT statement
            0110 ;
            0120 AUXBR = $AF
            0130 CIX =   $F2
            0140 COX =   $94
            0150 FASC =  $D8E6
            0160 FR0 =   $D4
            0170 FTARV = $AB90
            0180 GETVAR = $ABE9
            0190 INBUFP = $F3
            0200 INIX =  $A8
            0210 INOUTX = $B491
            0220 IOCHN = $B5
            0230 IXGDAT = $BD07
            0240 PTABW = $C9
            0250 RSTHIB = $B48F
            0260 STMCUR = $8A
            0270 VART =  $D2
            0280 XLET =  $AADA
            0290 ;
            0300     *=  $B3DA
            0310 ;
            0320     LDA PTABW
            0330     STA AUXBR
            0340     LDA #$00
            0350     STA COX
            0360 PRNT LDY INIX
            0370     LDA (STMCUR),Y
            0380     CMP #$12          ,
            0390     BEQ COM
            0400     CMP #$16          EOL
            0410     BEQ EOL
            0420     CMP #$14          :
            0430     BEQ EOL
            0440     CMP #$15          ;
            0450     BEQ SCL
            0460     CMP #$1C          #
            0470     BEQ DVC
            0480     JSR XLET
            0490     JSR GETVAR
            0500     DEC INIX
            0510     BIT VART
            0520     BMI ARR
            0530     LDA FR0+1
            0540     CMP #$10
            0550     BCC ASC
            0560     LDA FR0+5
            0570     AND #$F0
            0580     STA FR0+5
            0590 ASC JSR FASC
            0600     LDA #$00
            0610     STA CIX
            0620 DIG LDY CIX
            0630     LDA (INBUFP),Y
            0640     PHA
            0650     INC CIX
            0660     JSR RSTHIB
            0670     PLA
            0680     BPL DIG
            0690     BMI PRNT
            0700 ARR JSR FTARV+3
            0710     LDA #$00
            0720     STA CIX
            0730 LOOP LDA FR0+2
            0740     BNE DCN
            0750     DEC FR0+3
            0760     BMI PRNT
            0770 DCN DEC FR0+2
            0780     LDY CIX
            0790     LDA (FR0),Y
            0800     INC CIX
            0810     BNE NXT
            0820     INC FR0+1
            0830 NXT JSR INOUTX
            0840     JMP LOOP
            0850 COM LDY COX
            0860     INY
            0870     CPY AUXBR
            0880     BCC TAB
            0890     CLC
            0900     LDA PTABW
            0910     ADC AUXBR
            0920     STA AUXBR
            0930     BCC COM
            0940 TAB LDY COX
            0950     CPY AUXBR
            0960     BCS SCL
            0970     LDA #$20
            0980     JSR RSTHIB
            0990     JMP TAB
            1000 EOL JMP RET           EOL & :
            1010 DVC JSR IXGDAT        #
            1020     STA IOCHN
            1030     DEC INIX
            1040     JMP PRNT
            1050 SCL INC INIX          ;
            1060     LDY INIX
            1070     LDA (STMCUR),Y
            1080     CMP #$16          EOL
            1090     BEQ END
            1100     CMP #$14          :
            1110     BEQ END
            1120     JMP PRNT
            1130 RET LDA #$9B
            1140     JSR INOUTX
            1150 END LDA #$00
            1160     STA IOCHN
            1170     RTS
    Token przecinka ($12) nakazuje przejście do następnej pozycji tabulacji. Jest to realizowane przy pomocy pętli, w której procedura RSTHIB zapisuje spacje (po jednej w każdym przejściu pętli). Licznikiem tej pętli jest rejestr AUXBR, który zawiera wielokrotność kroku tabulacji (przepisanego z rejestru PTABW) zmniejszoną o aktualną pozycję kursora w zapisywanym wierszu. Gdy wszystkie wymagane spacje zostaną już zapisane, następuje przeskok do fragmentu procedury XPRNT realizującego token średnika (;).

    Procedura RSTHIB (i jej fragment oznaczony etykietą INOUTX) zwiększa stan licznika wyjściowego COX i przekazuje znak podany w akumulatorze do procedury PRPCHN. W ten sposób znak z akumulatora zostaje wysłany do urządzenia zewnętrznego. Przy wywołaniu od RSTHIB dodatkowo w zapisywanym znaku kasowany jest najstarszy bit.
            0100 COX =   $94
            0110 PRPCHN = $BA99
            0120 ;
            0130     *=  $B48F
            0140 ;
            0150 ;ReSeT HIgh Bit
            0160 ;
            0170 RSTHIB AND #$7F
            0180 ;
            0190 ;INcrease OUTput indeX
            0200 ;
            0210 INOUTX INC COX
            0220     JMP PRPCHN

6.6.7. Instrukcja LPRINT

    Instrukcja LPRINT ma podobne zadanie jak PRINT, lecz w tym przypadku zapis wykonywany jest zawsze na drukarkę i przez kanał IOCB 7. Realizuje to procedura XLPRNT. Rozpoczyna ją ustawienie wektora INBUFP na nazwę urządzenia PRTNAM (drukarka - P:) i wpisanie do rejestru IOCHN numeru kanału ($07). Następnie urządzenie jest otwierane do zapisu przez wywołanie procedury PRPOPN z wartością $08 (zapis) w rejestrze Y i $00 w akumulatorze. Po sprawdzeniu poprawności otwarcia przez procedurę ENDIO właściwy zapis realizowany jest przez XPRINT. Po wykonaniu operacji wykorzystywany kanał IOCB jest zamykany przez procedurę CLCHN.
            0100 ;eXecute LPRINT statement
            0110 ;
            0120 CLCHN = $BCF7
            0130 ENDIO = $BCBB
            0140 INBUFP = $F3
            0150 IOCHN = $B5
            0160 PRPOPN = $BBD8
            0170 XPRINT = $B3DA
            0180 ;
            0190     *=  $B496
            0200 ;
            0210     LDA # <PRTNAM
            0220     STA INBUFP
            0230     LDA # >PRTNAM
            0240     STA INBUFP+1
            0250     LDX #$07
            0260     STX IOCHN
            0270     LDA #$00
            0280     LDY #$08
            0290     JSR PRPOPN
            0300     JSR ENDIO
            0310     JSR XPRINT
            0320     JMP CLCHN
            0330 ;
            0340 PRTNAM .BYTE "P:",$9B

6.6.8. Instrukcja POINT

    Instrukcja POINT ustawia głowicę zapisująco-odczytującą stacji dysków na podanym bajcie we wskazanym sektorze. Jej procedurą wykonawczą jest XPOINT, która po ustaleniu potrzebnych parametrów wywołuje systemową procedurę CIOMAIN.
            0100 ;eXecute POINT statement
            0110 ;
            0120 FR0 =   $D4
            0130 GLNNUM = $ABCD
            0140 ICAX3 = $034C
            0150 ICAX4 = $034D
            0160 ICAX5 = $034E
            0170 IOCMD = $C0
            0180 IOOPER = $BC29
            0190 MLTCHN = $BCAF
            0200 SETDVC = $BCA8
            0210 ;
            0220     *=  $BC54
            0230 ;
            0240     JSR SETDVC
            0250     JSR GLNNUM
            0260     JSR MLTCHN
            0270     LDA FR0
            0280     STA ICAX3,X
            0290     LDA FR0+1
            0300     STA ICAX4,X
            0310     JSR GLNNUM
            0320     JSR MLTCHN
            0330     LDA FR0
            0340     STA ICAX5,X
            0350     LDA #$25
            0360     STA IOCMD
            0370     BNE IOOPER
    Pierwszym parametrem jest numer kanału IOCB, który jest pobierany z bufora wejściowego przez procedurę SETDVC. Pozostałe parametry odczytywane są przez dwukrotne wywołanie procedury GLNNUM, przy czym procedura MLTCHN służy każdorazowo do obliczenia poprawnego adresu IOCB. Odczytane wartości są umieszczane w rejestrach ICAX3 i ICAX4 (numer sektora) oraz ICAX5 (numer bajtu w sektorze). Po tych przygotowaniach do rejestru IOCMD wpisywany jest kod operacji POINT ($25) i wykonywany jest skok do procedury IOOPER, która wywołuje systemową procedurę I/O.

6.6.9. Instrukcja NOTE

    Odwrotnością POINT jest instrukcja NOTE. Odczytuje ona pozycję głowicy stacji dysków i uzyskane rezultaty przypisuje dwóm wskazanym zmiennym. Procedura wykonawcza tej instrukcji - XNOTE - jest także odwróceniem procedury XPOINT.
            0100 ;eXecute NOTE statement
            0110 ;
            0120 ICAX3 = $034C
            0130 ICAX4 = $034D
            0140 ICAX5 = $034E
            0150 MLTCHN = $BCAF
            0160 PRCIO = $BC24
            0170 SAVBYT = $BD31
            0180 SAVWRD = $BD33
            0190 ;
            0200     *=  $BC3D
            0210 ;
            0220     LDA #$26
            0230     JSR PRCIO
            0240     LDA ICAX3,X
            0250     LDY ICAX4,X
            0260     JSR SAVWRD
            0270     JSR MLTCHN
            0280     LDA ICAX5,X
            0290     JMP SAVBYT
    Rozpoczyna ją wywołanie procedury PRCIO z umieszczonym w akumulatorze kodem operacji NOTE ($26). Numer sektora, w którym aktualnie znajduje się głowica stacji dysków, odczytywany jest z rejestrów ICAX3 i ICAX4, a następnie przekazywany do odpowiedniej zmiennej przez procedurę SAVWRD. Analogicznie, procedura SAVBYT przypisuje zmiennej numer bajtu odczytany z rejestru ICAX5.

6.6.10. Instrukcje INPUT i READ

    Instrukcje INPUT i READ służą do odczytu informacji, przy czym INPUT dokonuje odczytu z urządzenia zewnętrznego (w tym także z edytora), zaś READ odczytuje dane zawarte w instrukcjach DATA. Odczytane dane są przypisywane umieszczonym w instrukcji zmiennym. W obu przypadkach dozwolony jest jednoczesny (w jednej instrukcji) odczyt dowolnej liczby danych dowolnego typu. Procedury wykonawcze tych instrukcji są ze sobą mocno powiązane i dlatego też muszą być opisywane razem.

    Procedura wykonawcza instrukcji READ - XREAD - rozpoczyna się od wpisania adresu wiersza z instrukcją DATA jako wektora bufora wejściowego. W tym celu aktualny numer wiersza jest zapamiętywany przy pomocy procedury SAVSTM, a zawartość rejestru DATALN (DATA LiNe Number) jest przepisywana do CLNN (Current LiNe Number). Następnie procedura FNDCST odszukuje ten wiersz w pamięci, a jego adres z rejestru STMCUR (StaTeMent CURrent address) jest przepisywany do wektora INBUFP (INput BUFfer Pointer). Teraz wywołanie procedury XRTRN odtwarza adres aktualnie wykonywanego wiersza z instrukcją READ. Podczas tych operacji stan licznika wejściowego INIX jest przechowywany na stosie. Trzeba tu zwrócić uwagę, że rejestr DATALN w momencie uruchomienia programu zawiera wartość $00, a później może być zmieniony tylko przez instrukcję READ (zob. dalej) i RESTORE (zob. rozdział 6.2.3).

    Teraz przez kilkakrotne wywoływanie procedury NXTDAT i stanowiącej jej fragment SENDDT odczytywane są parametry znalezionego wiersza. Są to kolejno: dwa bajty numeru wiersza przepisywane do DATALN, długość wiersza przepisywana do pierwszego bajtu rejestru ZTEMP1 i długość instrukcji przepisywana do drugiego bajtu ZTEMP1. Procedura NXTDAT nie jest tu jedank wykorzystywana zgodnie ze swoim przeznaczeniem. Zasadniczo służy ona do poszukiwania końca odczytywanej danej, bowiem w rezultacie jej wywołania bit Zero statusu procesora jest ustawiany, gdy odczytanym znakiem jest przecinek (,) lub koniec wiersza (EOL). W każdym innym przypadku bit Zero pozostaje skasowany.
            0100 CIX =   $F2
            0110 INBUFP = $F3
            0120 ;
            0130     *=  $B32D
            0140 ;
            0150 ;NeXT DATa
            0160 ;
            0170 NXTDAT INC CIX
            0180 ;
            0190 ;Search for END of DaTa
            0200 ;
            0210 SENDDT LDY CIX
            0220     LDA (INBUFP),Y
            0230     CMP #',
            0240     CLC
            0250     BEQ END
            0260     CMP #$9B
            0270 END RTS
    Ostatnie w tej fazie wywołanie NXTDAT zwraca token pierwszej instrukcji w wierszu. Jeżeli nie jest to instrukcja DATA (token $01), poszukiwany jest token następnej instrukcji w tym samym wierszu. Po dotarciu do końca wiersza zerowany jest znacznik DATAD i przeszukiwany jest następny wiersz programu, aż do napotkania wiersza o numerze przekraczającym $7FFF. W takim przypadku przez skok do procedury ODATER sygnalizowany jest błąd (Out of DATa ERror). Następny wiersz poszukiwany jest także wtedy, gdy stan licznika DATAD przekracza wartość pierwszego bajtu rejestru ZTEMP1. Po znalezieniu danej, która ma zostać odczytana, w rejestrze SXFLG (SyntaX FLaG) umieszczana jest wartość $40, która pozwoli później rozpoznać rodzaj wykonywanej instrukcji.
0100 ACHNN = $B4              0610     STA INIX
0110 AFP =   $D800            0620 LOOP LDY #$00
0120 BINPER = $B924           0630     STY CIX
0130 CIX =   $F2              0640     JSR SENDDT
0140 CLNN =  $A0              0650     STA DATALN
0150 DATAD = $B6              0660     JSR NXTDAT
0160 DATALN = $B7             0670     STA DATALN+1
0170 FNDCST = $A9A2           0680     JSR NXTDAT
0180 GETIX = $B904            0690     STA ZTEMP1
0190 GIRQST = $A9F2           0700 NXT1 JSR NXTDAT
0200 INBUFP = $F3             0710     STA ZTEMP1+1
0210 INIX =  $A8              0720     JSR NXTDAT
0220 INPREC = $BDE4           0730     EOR #$01
0230 IXGDAT = $BD07           0740     BEQ SDT
0240 NXTDAT = $B32D           0750     LDY ZTEMP1+1
0250 ODATER = $B928           0760     CPY ZTEMP1
0260 PROMPT = $C2             0770     BCS BPS1
0270 PUTVAR = $ABB2           0780     DEY
0280 RECVAL = $AB36           0790     STY CIX
0290 RSTPTR = $AB26           0800     BCC NXT1
0300 SAVSTM = $B6F9           0810 BPS1 STY CIX
0310 SAVVAL = $AC0C           0820     DEC CIX
0320 SENDDT = $B32F           0830 GET LDY #$01
0330 STBV =  $DA51            0840     LDA (INBUFP),Y
0340 STMCUR = $8A             0850     BMI RERR
0350 STTXT = $AB5C            0860     SEC
0360 SXFLG = $A6              0870     LDA CIX
0370 VART =  $D2              0880     ADC INBUFP
0380 XRTRN = $BDA8            0890     STA INBUFP
0390 XSLET = $AE8E            0900     LDA #$00
0400 XSTOP = $B792            0910     STA DATAD
0410 ZTEMP1 = $F5             0920     ADC INBUFP+1
0420 ;                        0930     STA INBUFP+1
0430     *=  $B2AE            0940     BCC LOOP
0440 ;                        0950 SDT STA ZTEMP1
0450 ;eXecute READ statement  0960 NDT LDA ZTEMP1
0460 ;                        0970     CMP DATAD
0470 XREAD LDA INIX           0980     BCS NLN
0480     PHA                  0990 NXT2 JSR NXTDAT
0490     JSR SAVSTM           1000     BNE NXT2
0500     LDA DATALN           1010     BCS GET
0510     STA CLNN             1020     INC ZTEMP1
0520     LDA DATALN+1         1030     BNE NDT
0530     STA CLNN+1           1040 NLN LDA #$40
0540     JSR FNDCST           1050     STA SXFLG
0550     LDA STMCUR           1060     INC CIX
0560     STA INBUFP           1070     BCS RTV
0570     LDA STMCUR+1         1080 ;
0580     STA INBUFP+1         1090     *=  $B33B
0590     JSR XRTRN            1100 ;
0600     PLA                  1110 RERR JSR ODATER

1120 ;                        1480     LDX #$FF
1130 ;eXecute INPUT statement 1490 NST INX
1140 ;                        1500     JSR NXTDAT
1150 XINPUT LDA #'?           1510     BNE NST
1160     STA PROMPT           1520     BCS FND
1170     JSR RECVAL           1530     BIT SXFLG
1180     DEC INIX             1540     BVC NST
1190     BCC INP              1550 FND LDY ZTEMP1
1200     JSR IXGDAT           1560     LDA INIX
1210     STA ACHNN            1570     PHA
1220 INP JSR STBV             1580     TXA
1230     JSR INPREC           1590     LDX #INBUFP
1240     JSR GIRQST           1600     JSR STTXT
1250     BEQ BREAK            1610     PLA
1260     LDY #$00             1620     STA INIX
1270     STY SXFLG            1630     JSR XSLET+3
1280     STY CIX              1640 CKE BIT SXFLG
1290 RTV JSR RECVAL           1650     BVC CKI
1300     INC INIX             1660     INC DATAD
1310     LDA VART             1670     JSR GETIX
1320     BMI TEXT             1680     BCS END
1330     JSR AFP              1690     JSR SENDDT
1340     BCS IERR             1700     BCC BPS2
1350     JSR SENDDT           1710     JMP GET
1360     BNE IERR             1720 CKI JSR GETIX
1370     JSR SAVVAL           1730     BCC NXGT
1380     JMP CKE              1740 END JSR STBV
1390 BREAK JMP XSTOP          1750     LDA #$00
1400 IERR LDA #$00            1760     STA ACHNN
1410     STA ACHNN            1770     RTS
1420     JSR BINPER           1780 NXGT JSR SENDDT
1430 TEXT JSR RSTPTR          1790     BCC BPS2
1440     JSR PUTVAR           1800     JMP INP
1450     DEC CIX              1810 BPS2 INC CIX
1460     LDA CIX              1820     JMP RTV
1470     STA ZTEMP1
    Odmienny jest początek procedury wykonawczej instrukcji INPUT - XINPUT. Najpierw w rejestrze PROMPT (PROMPT character) umieszczany jest kod znaku zapytania (?) i wywoływana jest procedura RECVAL. Rozpoznaje ona wartość stanowiącą pierwszy parametr instrukcji. Jeśli jest to znak "#", to następująca po nim liczba jest odczytywana przez procedurę IXGDAT i przepisywana do rejestru ACHNN (Auxiliary CHaNnell Number). Następnie odtwarzany jest przy pomocy STBV wektor bufora wejściowego i wywoływana jest procedura INPREC. Pobiera ona rekord (ciąg znaków zakończony przez RETURN) z urządzenia zewnętrznego. Jeśli urządzeniem tym jest edytor (IOCB 0), to najpierw na ekranie jest umieszczany znak z rejestru PROMPT.

    Po zakończeniu INPREC wywoływana jest procedura GIRQST, która sprawdza, czy wykonywana operacja nie została przerwana przez naciśnięcie klawisza BREAK. W takim przypadku wykonywany jest skok do procedury XSTOP, która przerywa działanie programu. Po poprawnym odczytaniu rekordu do rejestru SXFLG wpisywana jest wartość $00, która oznacza instrukcję INPUT (zob. wyżej).

    Niektóre źródła podają, że przez zmianę wartości w rejestrze PROMPT można zmienić znak wyświetlany przez instrukcję INPUT. W świetle tego, co zostało wyżej napisane, jest to niemożliwe, gdyż przed wykonaniem INPUT do rejestru PROMPT wpisywany jest kod znaku zapytania. Taka zmiana wymaga więc zmiany w samym interpreterze Atari Basic.
            0100 ACHNN = $B4
            0110 BFLN1 = $BD0F
            0120 ENDIO = $BCBB
            0130 PROMPT = $C2
            0140 PRPCHN = $BA99
            0150 SAVCMD = $BABE
            0160 ;
            0170     *=  $BDDB
            0180 ;
            0190 ;PUT RETurn
            0200 ;
            0210 PUTRET LDX ACHNN
            0220     BNE GETREC
            0230     LDA #$9B
            0240     JSR PRPCHN
            0250 ;
            0260 ;INPut RECord
            0270 ;
            0280 INPREC LDX ACHNN
            0290     BNE GETREC
            0300     LDA PROMPT
            0310     JSR PRPCHN
            0320 ;
            0330 ;GET RECord
            0340 ;
            0350 GETREC LDX ACHNN
            0360     LDA #$05
            0370     JSR SAVCMD
            0380     JSR BFLN1
            0390     JMP ENDIO
    Od tego miejsca przebieg obu procedur jest prawie jednakowy. Najpierw przez wywołanie procedury RECVAL rozpoznawany jest typ zmiennej. Zmienna liczbowa jest zamieniana przy pomocy procedury AFP z ciągu cyfr w kodzie ASCII na postać zmiennoprzecinkową. Gdy podczas tej zamiany wystąpi błąd lub następny znak nie oznacza końca danej, to procedura jest przerywana skokiem do BINPER, gdzie sygnalizowany jest błąd (Bad INPut ERror). Poprawna wartość jest natomiast przypisywana odpowiedniej zmiennej przez wywołanie procedury SAVVAL.

    W przypadku zmiennej tekstowej jej parametry są umieszczane przy pomocy procedury PUTVAR w buforze wyjściowym odtworzonym przez wywołanie RSTPTR. Następnie jest odszukiwany koniec zmiennej przez kolejne wywołania procedury NXTDAT, przy czym dla instrukcji INPUT znakiem końca danej jest tylko znak RETURN (EOL), zaś dla READ także przecinek. Teraz cały ciąg jest przepisywany do bufora wejściowego przez procedurę STTXT, a potem przypisywany odpowiedniej zmiennej przez wywołanie XSLET.

    Teraz procedura GETIX sprawdza, czy jest to koniec instrukcji, w przypadku instrukcji READ jest ponadto zwiększany licznik DATAD (DATa ADdress). Jeżeli cała instrukcja została wykonana, to procedura STBV odtwarza wektor bufora, zerowany jest rejestr ACHNN, a procedury XREAD i XINPUT kończą się rozkazem RTS. Jeśli konieczne są następne dane, to dla instrukcji INPUT są one ponownie pobierane z podanego urządzenia (skok do etykiety INP). Kolejna dana dla instrukcji READ jest odczytywana, gdy koniec poprzedniej był oznaczony przecinkiem (skok do etykiety RTV). W innym przypadku poszukiwana jest następna instrukcja DATA (skok do GET).

6.6.11. Instrukcje SAVE i CSAVE

    Instrukcja SAVE służy do zapisu stokenizowanego programu w Atari Basic na dowolnym urządzeniu zewnętrznym. Podobna do niej instrukcja CSAVE dokonuje tego zapisu zawsze na magnetofon. Procedury wykonawcze tych instrukcji - XSAVE i XCSAVE - różnią się jedynie sposobem otwarcia kanału 7, a ich dalszy przebieg (procedura SAVE) jest identyczny. Procedury te (a także procedury wykorzystywane przez inne instrukcje) korzystają z kanału IOCB 7. Należy więc unikać używania tego kanału we własnych programach.
            0100 ;OPeN CHannel #7
            0110 ;
            0120 CIOEXE = $BD2B
            0130 IOCMD = $C0
            0140 IODVC = $C1
            0150 MLTCHN = $BCAF
            0160 OPNCHN = $BC02
            0170 ;
            0180     *=  $BAD7
            0190 ;
            0200     PHA
            0210     LDY #$07
            0220     STY IODVC
            0230     JSR MLTCHN
            0240     LDA #$0C
            0250     JSR CIOEXE
            0260     LDY #$03
            0270     STY IOCMD
            0280     PLA
            0290     LDY #$00
            0300     JSR OPNCHN
            0310     LDA #$07
            0320     RTS
    Procedura XSAVE po umieszczeniu w akumulatorze wartości $08, która wskazuje zapis, wywołuje procedurę OPNCH7. Tu najpierw kanał IOCB 7 jest zamykany, a dopiero potem ponownie otwierany do zapisu. Ponieważ jako drugi parametr pomocniczy (do rejestru ICAX2) jest przesyłana do procedury OPNCHN wartość $00, to w przypadku magnetofonu zapis będzie się odbywał z długimi przerwami. Wykonywane tu zamknięcie kanału przed jego otwarciem pozwala ustrzec się przed ewentualnymi błędami, których wystąpienie jest możliwe przy stosowaniu instrukcji CSAVE (zob. niżej).
            0100 ;OPeN CASsette
            0110 ;
            0120 ENDIO = $BCBB
            0130 INBUFP = $F3
            0140 PRPOPN = $BBD8
            0150 ;
            0160     *=  $BBB4
            0170 ;
            0180     NOP
            0190     NOP
            0200     PHA
            0210     LDX # <CASNAM
            0220     STX INBUFP
            0230     LDX # >CASNAM
            0240     STX INBUFP+1
            0250     LDX #$07
            0260     PLA
            0270     TAY
            0280     LDA #$80
            0290     JSR PRPOPN
            0300     JSR ENDIO
            0310     LDA #$07
            0320     RTS
            0330 ;
            0340 CASNAM .BYTE "C:",$9B
    Procedura XCSAVE także umieszcza w akumulatorze wartość $08, lecz następnie wywołuje procedurę OPNCAS. Nie zamyka ona kanału 7 przed jego otwarciem, co może być przyczyną błędów, jeśli kanał ten jest wykorzystywany w programie. Sama operacja otwarcia jest przeprowadzona podobnie jak w opisanej wcześniej procedurze XLPRNT (instrukcja LPRINT). Trzeba tu jednak zwrócić uwagę na wartość $80 przekazywaną do PRPOPN. Jest ona tam następnie przepisywana do rejestru ICAX2 i powoduje zapis z krótkimi przerwami pomiędzy rekordami na kasecie.
            0100 BFLN3 = $BD15
            0110 BFLN4 = $BD17
            0120 CLCHN = $BCF7
            0130 ENDIO = $BCBB
            0140 INBUFP = $F3
            0150 IOCMD = $C0
            0160 LBUFF = $0580
            0170 LOMEM = $80
            0180 MLTCHN = $BCAF
            0190 OPNCAS = $BBB4
            0200 OPNCH7 = $BAD7
            0210 RUNSTK = $8E
            0220 VNTP =  $82
            0230 ;
            0240     *=  $BB6D
            0250 ;
            0260 ;eXecute SAVE statement
            0270 ;
            0280 XSAVE LDA #$08
            0290     JSR OPNCH7
            0300 ;
            0310 ;SAVE routine
            0320 ;
            0330 SAVE LDA #$0B
            0340     STA IOCMD
            0350     LDX #LOMEM
            0360 LOOP SEC
            0370     LDA $00,X
            0380     SBC LOMEM
            0390     STA [LBUFF-LOMEM],X
            0400     INX
            0410     LDA $00,X
            0420     SBC LOMEM+1
            0430     STA [LBUFF-LOMEM],X
            0440     INX
            0450     CPX #RUNSTK
            0460     BCC LOOP
            0470     JSR MLTCHN
            0480     LDY #$0E
            0490     JSR BFLN3
            0500     JSR ENDIO
            0510 ;
            0520 ;PRoGraM area TRansmit
            0530 ;
            0540 PRGMTR JSR MLTCHN
            0550     LDA VNTP
            0560     STA INBUFP
            0570     LDA VNTP+1
            0580     STA INBUFP+1
            0590     LDY LBUFF+$0D
            0600     DEY
            0610     TYA
            0620     LDY LBUFF+$0C
            0630     JSR BFLN4
            0640     JSR ENDIO
            0650     JMP CLCHN
            0660 ;
            0670     *=  $BBD1
            0680 ;
            0690 ;eXecute CSAVE statement
            0700 ;
            0710 XCSAVE LDA #$08
            0720     JSR OPNCAS
            0730     BNE SAVE
    Procedura SAVE po zapisaniu do rejestru IOCMD kodu operacji PUT BYTE ($0B), realizuje zapisanie programu w dwóch etapach. W pierwszym etapie zapisywane są względne wartości wektorów stosowanych przez interpreter (LOMEM, VNTP, VNTD, VVTP, STMTAB, STMCUR i STARP). Wartości względne są uzyskiwane przez odjęcie od każdego wektora wielkości LOMEM. Dzięki temu program będzie działał poprawnie po odczycie, niezależnie od aktualnej wartości dolnej granicy dostępnej pamięci RAM. Czyni to program całkowicie relokowalnym i pozwala na zainstalowanie przed odczytem programu DOS-u lub dodatkowych procedur pomocniczych w języku maszynowym (tzw. akcesoriów). Po przepisaniu tych wektorów do bufora LBUFF (Line BUFFer) są one zapisywane na urządzenie przez wywołanie procedury BFLN. Poprawność tego zapisu jest sprawdzana przy pomocy procedury ENDIO.

    W drugim etapie zapisywana jest cała treść programu wraz ze zmiennymi (tablica nazw zmiennych, tablica wartości zmiennych i tablica instrukcji). W tym celu jako adres bufora do zapisu podawana jest zawartość wektora VNTP, a długość bufora określana jest według zmniejszonej o jeden względnej wartości wektora STARP. Tak określona zawartość bufora jest zapisywana przez ponowne wywołanie procedury BFLN. Po sprawdzeniu poprawności wykonanej operacji przez ENDIO procedura SAVE kończy się skokiem do CLCHN, gdzie wykorzystywany kanał IOCB jest zamykany.

6.6.12. Instrukcje LOAD i CLOAD

    Instrukcje LOAD i CLOAD służą do odczytu stokenizowanego programu i stanowią odpowiedniki instrukcji SAVE i CSAVE. Poza punktami wywołań XLOAD i XCLOAD ich procedura wykonawcza posiada jeszcze etykietę LDPRGM. Służy ona do realizacji odczytu przez instrukcję RUN w przypadku uruchamiania programu z urządzenia zewnętrznego. Rodzaj instrukcji jest rozpoznawany według wartości odkładanej na stosie na początku procedury ($00 dla LOAD i CLOAD, $FF dla RUN).
            0100 BFLN3 = $BD15
            0110 ENDIO = $BCBB
            0120 IOCMD = $C0
            0130 LBUFF = $0580
            0140 LOADER = $B90A
            0150 LOADFLG = $CA
            0160 LOMEM = $80
            0170 MEMTOP = $02E5
            0180 MLTCHN = $BCAF
            0190 OPNCAS = $BBB4
            0200 OPNCH7 = $BAD7
            0210 PRGMTR = $BB98
            0220 PRLGER = $B90E
            0230 STARP = $8C
            0240 VNTP =  $82
            0250 WRMST = $A050
            0260 XCLR =  $B766
            0270 ;
            0280     *=  $BAF7
            0290 ;
            0300 ;LoaD PRoGraM
            0310 ;
            0320 LDPRGM LDA #$FF
            0330     BNE EXE
            0340 ;
            0350 ;eXecute LOAD statement
            0360 ;
            0370 XLOAD LDA #$00
            0380 EXE PHA
            0390     LDA #$04
            0400     JSR OPNCH7
            0410     PLA
            0420 ;
            0430 ;LOAD routine
            0440 ;
            0450 LOAD PHA
            0460     LDA #$07
            0470     STA IOCMD
            0480     STA LOADFLG
            0490     JSR MLTCHN
            0500     LDY #$0E
            0510     JSR BFLN3
            0520     JSR ENDIO
            0530     LDA LBUFF
            0540     ORA LBUFF+1
            0550     BNE ERR
            0560     LDX #STARP
            0570 LOOP CLC
            0580     LDA LOMEM
            0590     ADC [LBUFF-LOMEM],X
            0600     PHP
            0610     CLC
            0620     ADC #$00
            0630     TAY
            0640     LDA LOMEM+1
            0650     ADC [LBUFF-LOMEM+1],X
            0660     PLP
            0670     ADC #$00
            0680     CMP MEMTOP+1
            0690     BCC WRT
            0700     BNE PLG
            0710     CPY MEMTOP
            0720     BCC WRT
            0730 PLG JMP PRLGER
            0740 WRT STA $01,X
            0750     STY $00,X
            0760     DEX
            0770     DEX
            0780     CPX #VNTP
            0790     BCS LOOP
            0800     JSR PRGMTR
            0810     JSR XCLR
            0820     LDA #$00
            0830     STA LOADFLG
            0840     PLA
            0850     BEQ WRM
            0860     RTS
            0870 WRM JMP WRMST
            0880 ERR LDA #$00
            0890     STA LOADFLG
            0900     JSR LOADER
            0910 ;
            0920 ;eXecute CLOAD statement
            0930 ;
            0940 XCLOAD LDA #$04
            0950     JSR OPNCAS
            0960     LDA #$00
            0970     BEQ LOAD
    Podobnie jak przy zapisie wykonywanie instrukcji rozpoczyna się od otwarcia kanału IOCB 7 przez odpowiednie procedury (OPNCH7 lub OPNCAS), lecz w tym przypadku do odczytu - wartość $04 w akumulatorze. Następnie do rejestru IOCMD wpisywany jest kod operacji GET BYTE ($07), a znacznik LOADFLG (LOADin FLaG) otrzymuje wartość niezerową. Znacznik ten pozwala po wystąpieniu błędu na rozpoznanie, czy sam odczyt był poprawny.

    Teraz przez wywołanie BFLN odczytywany jest pierwszy blok informacji, czyli względne wartości wektorów. Jeśli dwa pierwsze bajty nie są zerami (LOMEM-LOMEM=0), to procedura jest przerywana skokiem do LOADER i sygnalizowany jest błąd (LOAD file ERror). Po dodaniu aktualnej zawartości LOMEM odczytane wektory są przepisywane do odpowiednich rejestrów. Wartość każdego z nich jest przy tym porównywana z wektorem MEMTOP, a jeśli go przekracza, to przez skok do procedury PRLGER sygnalizowany jest błąd (PRogram too LonG ERror).

    Druga faza (odczyt treści programu) jest realizowana przez wywołanie procedury PRGMTR, która jest fragmentem SAVE. Dla zapewnienia poprawnej pracy programu jest teraz wywoływana procedura XCLR kasująca wartości i deklaracje wszystkich zmiennych. Po zakończeniu odczytu zerowany jest znacznik LOADFLG. Sposób opuszczenia procedury LOAD zależy od wartości zdjętej ze stosu. Zero (instrukcja LOAD lub CLOAD) powoduje skok do WRMST i gorący start interpretera. Inne wartości wskazują na wywołanie z procedury XRUN i powrót do niej jest wykonywany przez rozkaz RTS.

6.6.13. Instrukcja ENTER

    Instrukcja ENTER pozwala na odczyt z urządzenia zewnętrznego programu zapisanego w postaci pliku znaków ASCII, to znaczy niestokenizowanego. Ponieważ jej procedura wykonawcza - XENTER - nie zmienia wektorów interpretera, to odczytywany program jest dołączany do znajdującego się już w pamięci.
            0100 ;eXecute ENTER statement
            0110 ;
            0120 ACHNN = $B4
            0130 OPNCH7 = $BAD7
            0140 SYNTAX = $A060
            0150 ;
            0160     *=  $BAC5
            0170 ;
            0180     LDA #$04
            0190     JSR OPNCH7
            0200     STA ACHNN
            0210     JMP SYNTAX
    Sam przebieg procedury jest bardzo prosty. Najpierw kanał 7 jest otwierany do odczytu przez wywołanie procedury OPNCH7, a jego numer umieszczany jest w rejestrze ACHNN (Auxiliary CHaNnel Number). Po tym procedura kończy się skokiem do SYNTAX. W ten sposób następuje wprowadzanie kolejnych wierszy programu na normalnych zasadach, lecz z wybranego urządzenia zewnętrznego zamiast z klawiatury.

6.6.14. Instrukcja LIST

    Instrukcja LIST służy do zapisu programu w postaci niestokenizowanej (plik znaków ASCII) na dowolnym urządzeniu zewnętrznym. Zapisywany może być cały program lub fragment określony podanymi numerami wierszy. Jeśli nie zostanie podane urządzenie do zapisu, to jest on wykonywany do edytora (na ekran w trybie zero). Instrukcja LIST jest realizowana przez procedurę XLIST.

    Rozpoczyna się ona od przygotowania standardowych parametrów instrukcji. Numer pierwszego zapisywanego wiersza w rejestrze CLNN (Current LiNe Number) jest ustalany na zero, zaś ostatniego - w rejestrze MAXLN (MAXimal LiNe number) - na $7FFF. Ponadto w rejestrze DSPFLG umieszczana jest wartość różna od zera, co pozwala na wyświetlanie na ekranie znaków specjalnych. Na zakończenie tej fazy przy pomocy procedury PRPCHN wyświetlany jest znak końca wiersza (RETURN) i wywoływana jest procedura SAVSTM, która zapisuje parametry aktualnie wykonywanego wiersza.

    Teraz rozpoznawane są kolejne parametry instrukcji LIST (jeśli istnieją). Jeżeli pierwsza wartość - odczytana przy pomocy procedury LETVAR - jest tekstowa, to oznacza ona urządzenie, na którym ma być wykonany zapis. W takim przypadku wywoływana jest procedura OPNWRT, która otwiera do zapisu kanał IOCB 7. Jej przebieg jest tak prosty, że nie wymaga żadnego komentarza.
            0100 ;OPeN for WRiTe
            0110 ;
            0120 IOCHN = $B5
            0130 OPNCH7 = $BAD7
            0140 ;
            0150     *=  $BACF
            0160 ;
            0170     LDA #$08
            0180     JSR OPNCH7
            0190     STA IOCHN
            0200     RTS
    Kolejna liczba (koniecznie) odczytana przez procedurę GLNNUM stanowi numer pierwszego z zapisywanych wierszy programu i jest przepisywana do rejestru CLNN. Ta sama wartość jest umieszczana w rejestrze MAXLN, gdy w instrukcji LIST nie ma więcej parametrów. W przeciwnym przypadku numer ostatniego zapisywanego wiersza (MAXLN) jest odczytywany przez ponowne wywołanie GLNNUM. Teraz według zawartości CLNN procedura FNDCST odszukuje w pamięci wiersz o takim numerze lub - jeśli go nie ma - o najmniejszym wyższym numerze i rozpoczyna się główna pętla procedury.
            0100 ;eXecute LIST statement
            0110 ;
            0120 CLCHN = $BCF7
            0130 CLNN =  $A0
            0140 DSPFLG = $02FE
            0150 FNDCST = $A9A2
            0160 FR0 =   $D4
            0170 GHISTM = $A9E1
            0180 GIRQST = $A9F2
            0190 GLNLEN = $A9DC
            0200 GLNNUM = $ABCD
            0210 INIX =  $A8
            0220 IOCHN = $B5
            0230 LETVAR = $AC06
            0240 LSTPLN = $B58E
            0250 MAXLN = $AD
            0260 NXTSTM = $A9D0
            0270 OPNWRT = $BACF
            0280 OUTIX = $A7
            0290 PRPCHN = $BA99
            0300 SAVSTM = $B6F9
            0310 STMCUR = $8A
            0320 VART =  $D2
            0330 XRTRN = $BDA8
            0340 ;
            0350     *=  $B4B5
            0360 ;
            0370     LDY #$00
            0380     STY CLNN
            0390     STY CLNN+1
            0400     DEY
            0410     STY MAXLN
            0420     LDA #$7F
            0430     STA MAXLN+1
            0440     STA DSPFLG
            0450     LDA #$9B
            0460     JSR PRPCHN
            0470     JSR SAVSTM
            0480 EXE LDY INIX
            0490     INY
            0500     CPY OUTIX
            0510     BCS CST
            0520     LDA INIX
            0530     PHA
            0540     JSR LETVAR
            0550     PLA
            0560     STA INIX
            0570     LDA VART
            0580     BPL LIN
            0590     JSR OPNWRT
            0600     JMP EXE
            0610 LIN JSR GLNNUM
            0620     STA CLNN+1
            0630     LDA FR0
            0640     STA CLNN
            0650     LDY INIX
            0660     CPY OUTIX
            0670     BEQ MAX
            0680     JSR GLNNUM
            0690 MAX LDA FR0
            0700     STA MAXLN
            0710     LDA FR0+1
            0720     STA MAXLN+1
            0730 CST JSR FNDCST
            0740 NXTLN JSR GHISTM
            0750     BMI END
            0760     LDY #$01
            0770     LDA (STMCUR),Y
            0780     CMP MAXLN+1
            0790     BCC LST
            0800     BNE END
            0810     DEY
            0820     LDA (STMCUR),Y
            0830     CMP MAXLN
            0840     BCC LST
            0850     BNE END
            0860 LST JSR LSTPLN
            0870     JSR GIRQST
            0880     BEQ END
            0890     JSR GLNLEN
            0900     JSR NXTSTM
            0910     JMP NXTLN
            0920 END LDA IOCHN
            0930     BEQ EXIT
            0940     JSR CLCHN
            0950     LDA #$00
            0960     STA IOCHN
            0970 EXIT STA DSPFLG
            0980     JMP XRTRN
    Przede wszystkim sprawdzane jest ewentualne osiągnięcie wyznaczonego zakresu wierszy programu. Pętla jest przerywana, jeśli wiersz do zapisu ma numer większy od zawartego w rejestrze MAXLN lub większy od $7FFF (czyli jest w trybie bezpośrednim). W takim przypadku następuje przejście do końcowej fazy procedury XLIST. Jeżeli zapis był wykonywany na kanał inny niż IOCB 0, to kanał ten jest zamykany przez wywołanie CLCHN, a rejestr IOCHN jest zerowany. Zerowany jest również - niezależnie od użytego IOCB - rejestr DSPFLG. Potem procedura XLIST jest opuszczana skokiem do XRTRN, gdzie odtwarzany jest numer wiersza zawierającego instrukcję LIST i jej adres w tym wierszu.

    Jeśli wiersz do zapisu mieści się w wyznaczonym zakresie, to jego zapis wykonuje procedura LSTPLN (zob. niżej). Następnie przy pomocy GIRQST sprawdzany jest stan klawisza BREAK. Gdy został on naciśnięty, procedura XLIST także jest przerywana. Jeśli nie, to przez wywołanie GLNLEN i NXTSTM znajdowany jest kolejny wiersz programu i pętla się powtarza.

    Poszczególne wiersze programu są zapisywane na wskazanym urządzeniu zewnętrznym przez procedurę LSTPLN. Najpierw odczytuje ona numer zapisywanego wiersza i zamienia go na ciąg znaków ASCII. Adres tego ciągu jest umieszczany w rejestrze POKADR i wywoływana jest procedura PTMSG2, która dokonuje zapisu numeru.
            0100 ;LiST Program LiNe
            0110 ;
            0120 BUFIX = $9F
            0130 FASC =  $D8E6
            0140 FR0 =   $D4
            0150 IFP =   $D9AA
            0160 INBUFP = $F3
            0170 INIX =  $A8
            0180 OUTIX = $A7
            0190 POKADR = $95
            0200 PRTLCN = $B5C2
            0210 PTMSG2 = $B586
            0220 STMCUR = $8A
            0230 ;
            0240     *=  $B58E
            0250 ;
            0260 LSTPLN LDY #$00
            0270     LDA (STMCUR),Y
            0280     STA FR0
            0290     INY
            0300     LDA (STMCUR),Y
            0310     STA FR0+1
            0320     JSR IFP
            0330     JSR FASC
            0340     LDA INBUFP
            0350     STA POKADR
            0360     LDA INBUFP+1
            0370     STA POKADR+1
            0380     JSR PTMSG2
            0390 ;
            0400 ;PRinT Program LiNe
            0410 ;
            0420 PRTPLN LDY #$02
            0430     LDA (STMCUR),Y
            0440     STA BUFIX
            0450     INY
            0460 LOOP LDA (STMCUR),Y
            0470     STA OUTIX
            0480     INY
            0490     STY INIX
            0500     JSR PRTLCN
            0510     LDY OUTIX
            0520     CPY BUFIX
            0530     BCC LOOP
            0540     RTS
    Teraz długość wiersza jest przepisywana do rejestru BUFIX (BUFfer IndeX) - będzie ona stanowić licznik tokenów wiersza. Następny token, który określa długość instrukcji umieszczany jest w liczniku OUTIX (OUTput IndeX), zaś numer kolejnego tokena liczony od początku wiersza w liczniku INIX (INput IndeX). Zawartość wiersza jest zapisywana kolejno instrukcja po instrukcji przez procedurę PRTLCN w pętli sterowanej wymienionymi wyżej licznikami.

    Procedura zapisu zawartości wiersza PRTLCN jest sterowana przez pomocniczą procedurę INCIX oraz będącą jej fragmentem CMPIX. Procedura ta porównuje stany liczników INIX i OUTIX. Jeżeli rezultat sygnalizuje zakończenie zapisywanej instrukcji, to, po zdjęciu ze stosu adresu powrotnego, procedura kończy się rozkazem RTS. Powoduje to powrót bezpośrednio do procedury LSTPLN z pominięciem miejsca wywołania w PRTLCN. W przeciwnym razie kolejny token jest odczytywany z wiersza i przekazywany w akumulatorze do procedury PRTLCN.
            0100 INIX =  $A8
            0110 OUTIX = $A7
            0120 STMCUR = $8A
            0130 ;
            0140     *=  $B661
            0150 ;
            0160 ;INCrease IndeX
            0170 ;
            0180 INCIX INC INIX
            0190 ;
            0200 ;CoMPare IndeX
            0210 ;
            0220 CMPIX LDY INIX
            0230     CPY OUTIX
            0240     BCS EXIT
            0250     LDA (STMCUR),Y
            0260     RTS
            0270 EXIT PLA
            0280     PLA
            0290     RTS
    Przy zapisie instrukcji pierwszy odczytany token porównywany jest najpierw z kodem opuszczonej instrukcji LET ($36). Jego rozpoznanie powoduje od razu przejście do następnej fazy procedury. Każdy inny token powoduje wywołanie procedury PUTSTM, która zapisuje słowo kluczowe tej instrukcji. Jeśli była to instrukcja REM ($00) lub DATA ($01) albo token oznaczał błąd składni ($37), to pozostała zawartość wiersza jest zapisywana bez żadnych zmian.

    Dla pozostałych instrukcji odczytywany jest następny token. Jego wartość większa od $7F oznacza numer zmiennej. Nazwa zmiennej o takim numerze jest odszukiwana w tablicy nazw zmiennych przez procedurę FNDPEL i zapisywana przy pomocy PUTTXT. Jeżeli koniec instrukcji nie został jeszcze osiągnięty, to rozpoznawany jest następny token.

    Wartość mniejsza od $0F (możliwa jest tylko $0E) sygnalizuje stałą liczbową. Stała ta jest odczytywana przez procedurę NUMBER i zamieniana na ciąg znaków ASCII. Zapis tego ciągu jest wykonywany przy użyciu procedury PUTTXT, identycznie jak numer wiersza w procedurze LSTPLN.

    Wartość tokena równa $0F wskazuje stałą tekstową. Najpierw długość tej stałej jest przepisywana do rejestru AUXBR i procedura PRPCHN zapisuje znak cudzysłowu ("). Teraz przy wykorzystaniu rejestru AUXBR jako licznika kolejne znaki stałej są zapisywane przez procedurę PRPCHN. Na końcu PRPCHN zapisuje jeszcze jeden znak cudzysłowu.
            0100 ;PRinT Line CoNtens
            0110 ;
            0120 AUXBR = $AF
            0130 CHKLTR = $A3EC
            0140 CMPIX = $B663
            0150 FASC =  $D8E6
            0160 FNDPEL = $B53E
            0170 INBUFP = $F3
            0180 INCIX = $B661
            0190 INIX =  $A8
            0200 NUMBER = $AB45
            0210 OPFN =  $A7DE
            0220 POKADR = $95
            0230 PRPCHN = $BA99
            0240 PTMSG1 = $B581
            0250 PUTSTM = $B66F
            0260 PUTTXT = $B567
            0270 VNTP =  $82
            0280 ;
            0290     *=  $B5C2
            0300 ;
            0310     JSR CMPIX
            0320     CMP #$36
            0330     BEQ CHCK
            0340     JSR PUTSTM
            0350     JSR CMPIX
            0360     CMP #$37
            0370     BEQ PUT
            0380     CMP #$02
            0390     BCS CHCK
            0400 PUT JSR INCIX
            0410     JSR PRPCHN
            0420     JMP PUT
            0430 CHCK JSR INCIX
            0440     BPL NUM
            0450     AND #$7F
            0460     STA AUXBR
            0470     LDX #$00
            0480     LDA VNTP+1
            0490     LDY VNTP
            0500     JSR FNDPEL
            0510     JSR PUTTXT
            0520     CMP #['(+$80]
            0530     BNE CHCK
            0540     JSR INCIX
            0550     JMP CHCK
            0560 NUM CMP #$0F
            0570     BEQ STR
            0580     BCS OPER
            0590     JSR NUMBER
            0600     DEC INIX
            0610     JSR FASC
            0620     LDA INBUFP
            0630     STA POKADR
            0640     LDA INBUFP+1
            0650     STA POKADR+1
            0660 PRNT JSR PUTTXT
            0670     JMP CHCK
            0680 STR JSR INCIX
            0690     STA AUXBR
            0700     LDA #'"
            0710     JSR PRPCHN
            0720     LDA AUXBR
            0730     BEQ END
            0740 CHR JSR INCIX
            0750     JSR PRPCHN
            0760     DEC AUXBR
            0770     BNE CHR
            0780 END LDA #'"
            0790     JSR PRPCHN
            0800     JMP CHCK
            0810 OPER SEC
            0820     SBC #$10
            0830     STA AUXBR
            0840     LDX #$00
            0850     LDA # >OPFN
            0860     LDY # <OPFN
            0870     JSR FNDPEL
            0880     JSR CMPIX
            0890     CMP #$3D
            0900     BCS PRNT
            0910     LDY #$00
            0920     LDA (POKADR),Y
            0930     AND #$7F
            0940     JSR CHKLTR
            0950     BCS PRNT
            0960     JSR PTMSG1
            0970     JMP CHCK
    Każdy token, inny niż dotychczas opisane, oznacza operator lub funkcję. Jest on zmniejszany o $10 i procedura FNDPEL odszukuje odpowiednią nazwę w tablicy OPFN. Znalezione operatory (oprócz logicznych) są zapisywane przez procedurę PTMSG1, a nazwy funkcji i operatory logiczne przez PUTTXT.

    Po zapisaniu każdego elementu instrukcji następuje przejście do początku głównej pętli (oznaczonego etykietą CHCK) procedury PRTCLN i rozpoznanie kolejnego tokena. Opuszczenie procedury jest realizowane wyłącznie w opisany wcześniej sposób poprzez procedurę INCIX.
Zientara Wojciech: Mapa pamięci Atari XL/XE. Procedury interpretera Basica, SOETO, Warszawa, 1988.