Powrót do spisu treści

Rozdział 3

OBSŁUGA BŁĘDÓW

    Zanim przystąpimy do analizy poszczególnych instrukcji Atari Basic należy zapoznać się ze sposobem obsługi błędów. Idea głównej procedury realizującej sygnalizację i obsługę błędów interpretera jest zbliżona do zastosowanej w DOS 2.0 (zob. "Mapa pamięci Atari XL/XE. Dyskowe systemy operacyjne").
            0100 ;Errors routine
            0110 ;
            0120 CLNN =  $A0
            0130 DSPFLG = $02FE
            0140 DSPLIN = $B993
            0150 ERRCOD = $B9
            0160 ERRSAV = $C3
            0170 FDEXST = $B6E0
            0180 FR0 =   $D4
            0190 GHISTM = $A9E1
            0200 POKADR = $95
            0210 PRTRET = $BD79
            0220 PUTSTM = $B66F
            0230 PUTTXT = $B567
            0240 RSTCHN = $BD5B
            0250 SAVCLN = $B7A6
            0260 STMCUR = $8A
            0270 SYNTAX = $A060
            0280 TRAPLN = $BC
            0290 ;
            0300     *=  $B90A
            0310 ;
            0320 ;LOAD file ERror
            0330 LOADER INC ERRCOD
            0340 ;DeViCe Number ERror
            0350 DVCNER INC ERRCOD
            0360 ;PRogram too LonG ERror
            0370 PRLGER INC ERRCOD
            0380 ;invalid CHARacter ERror
            0390 CHARER INC ERRCOD
            0400 ;SyNTaX ERror
            0410 SNTXER INC ERRCOD
            0420 ;RETurn ERror
            0430 RETER INC ERRCOD
            0440 ;GOSub Line ERror
            0450 GOSLER INC ERRCOD
            0460 ;Line Too LonG ERror
            0470 LTLGER INC ERRCOD
            0480 ;No matching FOR ERror
            0490 NFORER INC ERRCOD
            0500 ;Line Not FounD ERror
            0510 LNFDER INC ERRCOD
            0520 ;OVerflow/UNderflow ERror
            0530 OVUNER INC ERRCOD
            0540 ;STack OVerflow ERror
            0550 STOVER INC ERRCOD
            0560 ;DIMension ERror
            0570 DIMER INC ERRCOD
            0580 ;Bad INPut ERror
            0590 BINPER INC ERRCOD
            0600 ;bad LINe Number ERror
            0610 LINNER INC ERRCOD
            0620 ;Out of DATa ERror
            0630 ODATER INC ERRCOD
            0640 ;String LENgth ERror
            0650 SLENER INC ERRCOD
            0660 ;Too Many VaRiables ERror
            0670 TMVRER INC ERRCOD
            0680 ;Bad VALue ERror
            0690 BVALER INC ERRCOD
            0700 ;INSufficient Memory ERror
            0710 INSMER INC ERRCOD
            0720 ;SUCCess
            0730 SUCC INC ERRCOD
            0740 ;
            0750 ;GET ERRor code
            0760 ;
            0770 GETERR LDA #$00
            0780     STA DSPFLG
            0790     JSR SAVCLN
            0800     LDA TRAPLN+1
            0810     BMI PRNT
            0820     STA CLNN+1
            0830     LDA TRAPLN
            0840     STA CLNN
            0850     LDA #$80
            0860     STA TRAPLN+1
            0870     LDA ERRCOD
            0880     STA ERRSAV
            0890     LDA #$00
            0900     STA ERRCOD
            0910     JMP FDEXST
            0920 PRNT JSR PRTRET
            0930     LDA #$37
            0940     JSR PUTSTM
            0950     LDA ERRCOD
            0960     STA FR0
            0970     LDA #$00
            0980     STA FR0+1
            0990     JSR DSPLIN
            1000 ;
            1010 ;Display STop MeSsaGe
            1020 ;
            1030 DSTMSG JSR GHISTM
            1040     BMI DRM
            1050     LDA # <LNMSG
            1060     STA POKADR
            1070     LDA # >LNMSG
            1080     STA POKADR+1
            1090     JSR PUTTXT
            1100     LDY #$01
            1110     LDA (STMCUR),Y
            1120     STA FR0+1
            1130     DEY
            1140     LDA (STMCUR),Y
            1150     STA FR0
            1160     JSR DSPLIN
            1170 DRM JSR PRTRET
            1180     LDA #$00
            1190     STA ERRCOD
            1200     JSR RSTCHN
            1210     JMP SYNTAX
            1220 ;
            1230     *=  $B9A4
            1240 ;
            1250 LNMSG .CBYTE " AT LINE "
    Miejsce rozpoczęcia procedury jest wybierane w zależności od rodzaju błędu. Kod błędu otrzymuje odpowiednią wartość przez kolejne zwiększanie zawartości rejestru ERRCOD (ERRor CODe). Właściwa procedura rozpoczyna się od wyzerowania rejestru DSPFLG (DiSPlay FLaG), który kontroluje sposób wyświetlania znaków na ekranie. Następnie wywoływana jest procedura SAVCLN. Odczytuje ona starszy bajt numeru wiersza, a gdy jest on mniejszy od $80 (tryb programowy), przepisuje numer aktualnie wykonywanego wiersza programu do rejestru STOPLN (STOP LiNe number). W obu przypadkach SAVCLN kończy się skokiem do procedury RSTCHN.
            0100 ;SAVe Current LiNe
            0110 ;
            0120 GHISTM = $A9E1
            0130 RSTCHN = $BD5B
            0140 STMCUR = $8A
            0150 STOPLN = $BA
            0160 ;
            0170     *=  $B7A6
            0180 ;
            0190     JSR GHISTM
            0200     BMI END
            0210     STA STOPLN+1
            0220     DEY
            0230     LDA (STMCUR),Y
            0240     STA STOPLN
            0250 END JMP RSTCHN
    Tu numer aktualnie używanego kanału wejścia/wyjścia jest ustawiany na zero, czyli na kanał IOCB obsługujący edytor ekranowy. Uzyskiwane jest to przez wyzerowanie rejestrów IOCHN (Input/Output CHaNnel) oraz ACHNN (Auxiliary CHaNnel Number).
            0100 ;ReSeT CHaNnel registers
            0110 ;
            0120 ACHNN = $B4
            0130 IOCHN = $B5
            0140 ;
            0150     *=  $BD5B
            0160 ;
            0170     LDA #$00
            0180     STA ACHNN
            0190     STA IOCHN
            0200     RTS
    Dalszy przebieg obsługi błędu zależy od zawartości rejestru TRAPLN (TRAP LiNe number). Jeśli znajduje się tam poprawny numer wiersza (mniejszy od $8000), to jest on przepisywany do rejestru CLNN (Current LiNe Number), a do starszego bajtu TRAPLN wpisywana jest wartość $80. Następnie kod błędu z ERRCOD jest przenoszony do ERRSAV (ERRor code SAVe register), a ERRCOD jest zerowany. Po wykonaniu tych operacji następuje skok do procedury FDEXST (wewnątrz XGOSUB) i realizacja programu jest kontynuowana.

    Jeśli rejestr TRAPLN nie zawiera poprawnego numeru wiersza, to najpierw wyświetlany jest znak końca wiersza (przy pomocy procedury PRTRET będącej częścią PRTPRM). Teraz w akumulatorze umieszczany jest kod tokena błędu ($37) i wywoływana jest procedura PUTSTM. Odszukuje ona, korzystając z pomocniczych procedur FNDPEL i ADDPAD, adres początkowy słowa kluczowego instrukcji w tabeli nazw STNAME. W tym przypadku jest to adres napisu "ERROR-". Adres ten jest zapisywany w rejestrze POKADR i następuje bezpośrednie przejście do procedury PTMSG.
            0100 ;PUT STateMent name
            0110 ;
            0120 AUXBR = $AF
            0130 FNDPEL = $B53E
            0140 PTMSG2 = $B586
            0150 STNAME = $A49F
            0160 ;
            0170     *=  $B66F
            0180 ;
            0190     STA AUXBR
            0200     LDX #$02
            0210     LDA # >STNAME
            0220     LDY # <STNAME
            0230     JSR FNDPEL
            0240     JMP PTMSG2
    Procedura FNDPEL odszukuje nazwę w odpowiedniej tablicy, której adres przekazany został w akumulatorze i rejestrze Y. Korzysta przy tym z zasady, że każda nazwa (instrukcji, operatora, funkcji i zmiennej) kończy się znakiem, którego najstarszy bit jest ustawiony. Zwiększanie zawartości rejestru POKADR jest wykonywane przez ADDPAD.

            0100 ;FiND Program ELement
            0110 ;
            0120 ADDPAD = $B557
            0130 AUXBR = $AF
            0140 POKADR = $95
            0150 SETPAD = $B562
            0160 STPTR = $AA
            0170 ;
            0180     *=  $B53E
            0190 ;
            0200     STX STPTR
            0210     JSR SETPAD
            0220 ELP LDY STPTR
            0230     DEC AUXBR
            0240     BMI ADDPAD
            0250 ILP LDA (POKADR),Y
            0260     BMI NXT
            0270     INY
            0280     BNE ILP
            0290 NXT INY
            0300     JSR ADDPAD
            0310     JMP ELP

            0100 POKADR = $95
            0110 ;
            0120     *=  $B557
            0130 ;
            0140 ;ADDition Poke ADdress
            0150 ;
            0160 ADDPAD CLC
            0170     TYA
            0180     ADC POKADR
            0190     STA POKADR
            0200     TAY
            0210     LDA POKADR+1
            0220     ADC #$00
            0230 ;
            0240 ;SET Poke ADdress
            0250 ;
            0260 SETPAD STA POKADR+1
            0270     STY POKADR
            0280     RTS
    Wyświetlenie odnalezionej nazwy jest wykonywane przez procedurę PTMSG. Przy jej wywołaniu od etykiety PTMSG1 przed nazwą wyświetlana jest jeszcze spacja ($20). Niezależnie od miejsca wywołania po wyświetlonej nazwie również umieszczana jest spacja. Sama nazwa jest wyświetlana poprzez procedurę PUTTXT.
            0100 ;PuT MeSsaGe
            0110 ;
            0120 PRPCHN = $BA99
            0130 PUTTXT = $B567
            0140 ;
            0150     *=  $B581
            0160 ;
            0170 PTMSG1 LDA #$20
            0180     JSR PRPCHN
            0190 PTMSG2 JSR PUTTXT
            0200     LDA #$20
            0210     JMP PRPCHN
    Korzystając z zawartego w rejestrze POKADR adresu procedura PUTTXT wyświetla napis znak po znaku, aż do napotkania RETURN lub znaku z ustawionym najstarszym bitem. Wykorzystywana przy tym procedura PRPCHN jest opisana w rozdziale 6.4.
            0100 ;PUT TeXT
            0110 ;
            0120 AUXBR = $AF
            0130 POKADR = $95
            0140 PRPCHN = $BA99
            0150 ;
            0160     *=  $B567
            0170 ;
            0180     LDY #$FF
            0190     STY AUXBR
            0200 LOOP INC AUXBR
            0210     LDY AUXBR
            0220     LDA (POKADR),Y
            0230     PHA
            0240     CMP #$9B
            0250     BEQ PUT
            0260     AND #$7F
            0270     BEQ NXT
            0280 PUT JSR PRPCHN
            0290 NXT PLA
            0300     BPL LOOP
            0310     RTS
    Po wyświetleniu napisu "ERROR-" do rejestru FR0 przepisywany jest kod błędu z ERRCOD i wywoływana jest procedura DSPLIN. Dokonuje ona zamiany dwubajtowej liczby całkowitej na ciąg znaków ASCII (przy pomocy IFP i FASC), a adres tego ciągu umieszcza w rejestrze POKADR. Następnie wykonywany jest skok do procedury PUTTXT, dzięki czemu kod błędu jest wyświetlany na ekranie.
            0100 ;DiSPlay LINe number
            0110 ;
            0120 FASC =  $D8E6
            0130 IFP =   $D9AA
            0140 INBUFP = $F3
            0150 POKADR = $95
            0160 PUTTXT = $B567
            0170 ;
            0180     *=  $B993
            0190 ;
            0200     JSR IFP
            0210     JSR FASC
            0220     LDA INBUFP
            0230     STA POKADR
            0240     LDA INBUFP+1
            0250     STA POKADR+1
            0260     JMP PUTTXT
    Jeżeli błąd wystąpił podczas wykonywania wiersza w trybie programowym (numer wiersza mniejszy od $8000), to przez wywołanie PUTTXT wyświetlany jest napis "AT LINE". Następnie po przepisaniu do FR0 numeru aktualnego wiersza procedura DSPLIN wyświetla ten numer na ekranie.

    Niezależnie od trybu pracy ostatnim wyświetlanym znakiem jest koniec wiersza (RETURN). Obsługa błędu kończy się wyzerowaniem rejestru ERRCOD i ponownym wywołaniem RSTCHN. Po wykonaniu wszystkich opisanych operacji interpreter przechodzi do procedury SYNTAX i oczekuje na polecenia od użytkownika.
Zientara Wojciech: Mapa pamięci Atari XL/XE. Procedury interpretera Basica, SOETO, Warszawa, 1988.