Rozdział 3OBSŁUGA BŁĘDÓWZanim 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. |