Powrót do spisu treści |
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 RSTCHNTu 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 RTSDalszy 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 PTMSG2Procedura 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 RTSWyś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 PRPCHNKorzystają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 RTSPo 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 PUTTXTJeż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. |