SPECTRUM ERROR HANDLING B. Twissell Program 1 loads a machine code routine into memory. If the checksum is correct you should save the code using: SAVE --- CODE 30000, 64 The dashes should be replaced with the filename of your choice. The routine is actually relocatable, which is a posh way of saying that it can be placed anywhere in memory. Thus you can load it again by: CLEAR 59999 LOAD --- CODE 60000 or whatever. To turn the error processing on, you simply call the routine, using: RANDOMIZE USR 30000 30000 is of course replaced by the appropriate address if you’ve loaded it elsewhere. This would normally be the first statement in the program, for the obvious reason that error processing is turned on before any errors can occur. This implies that you should load the machine code routine before loading the BASIC program. ERRNR REPORT 255 0 (OK) 0, 1-8 l,2,...9 9,10,...26 A,B...R Program l 10 REM -------------------------------- Implements an ON ERROR facility in Spectrum BASIC. See text. -------------------------------- 20 CLEAR 29999 30LET address = 30000 40 LET h$= "210f000922b05ceb2a 3d5c732372c93a3a5c3c2802fe09ca03 1321445ccb7e280b3a475c3c772a455c 22425c2100007c32715c220b5c2ab05c e52a425cc39e1b" 50 LET sum=0 60 FOR i=1 TO LEN h$ STEP 2 70 LET byte=l6*FN d(h$(i)) +FN d(h$(i+1)) 80 POKE address+(i-1)/2,byte 90 LET sum=sum+byte 100 NEXT i ll0 IF sum<>5087 THEN PRINT FLASH 1 '''"Line 40 is wrong!!!!" 120 DEF FN d(c$)=CODE c$ -(CODE "0" AND c$<="9") -(CODE "a"-10 AND c$>="a") Program 2 10 REM -------------------------------- Example of ON ERROR facility. This assumes that the necessary machine code routine is in memory at address 30000. -------------------------------- 20 RANDOMIZE USR 30000: LET errnr=23610: LET ok=255: LET number too big=5: LET stop in input=16: LET invalid file name=l4: LET tape loading error=26 30 PRINT "Setting up array." '"You can't BREAK this" '"(try it and see!!)" 40 DIM n(300) 50 FOR i=1 TO 300 60 POKE errnr,ok 70 LET n(i)=1/INT(10*RND) 80 IF PEEK errnr=number too big THEN PRINT "overflow" 90 NEXT i 100 REM LOOP ll0 POKE errnr,ok 120 INPUT "Enter file name" '"STOP (shift-6) is" '"ineffective..."' LINE f$ 130 IF PEEK errnr=stop in input THEN GO TO 110 I40 REM END LOOP 150 REM LOOP 160 SAVE f$ DATA n() 170 IF PEEK errnr=invalid file name THEN STOP 180 PRINT "Now to verify." '"If it fails, the SAVE" '"will be repeated." '"BREAK will get you out." 190 POKE errnr, ok 200 VERIFY f$ DATA n() 210 IF PEEK errnr=tape loading error THEN GO TO 160 220 REM END LOOP 230 PRINT "Finished" 240 STOP ON ERROR machine code ; ------------------------------ ; Adds ON ERROR facility to ; Spectrum BASIC. See text. ; .............................. ; ; First of all there is a short ; piece of code to turn on the ; error processing. This is a ; matter of working out the ; address of the label - ; when this is invoked by USR in ; BASIC, BC will have the value ; of , and is 15 ; bytes away — then the address ; of is stored in two ; places: an unused location at ; 23728; and into the location ; pointed to by ERRSP... ; turnon LD HL,15 ADD HL,BC LD (23723),HL EX DE,HL LD HL,(ERRSP) LD (HL),E INC HL LD (HL),D RET ; ; The BASIC interpreter may ; detect any error at all sorts ; of places. However, the action ; taken is always the same ; (except, that is, for errors ; from Interface l). The ; interpreter clears all the junk ; from the Z80's stack. Since ; the length of the stack depends ; on where the error occurred, ; ERRSP always points to the 2nd ; value left on the top is an ; address. Normally it is 1303H; ; the code at this address prints ; an error message and prepares ; to receive a command. The ; error processing is turned on ; (above) by changining this ; address on the stack. Thus ; when an error occurs, the stack ; is cleared and our code is ; invoked. ; For error numbers 0 (ok) and 9 ; (STOP statement) we allow the ; program to terminate by jumpinq ; to the code which was supposed ; to be executed... ; on LD A, (ERRNR) INC A JR Z,L1 CP 9 L1 JP Z,1303H ; ; if a jump is about to take ; place, bit 7 of NSPPC will be ; 0 - we do nothing. Otherwise, ; we set up NEWPPC and NSPPC with ; the line number and statement ; which is to be executed next ; (this is one more than the ; current statement)... ; LD HL,NSPPC BIT 7,(HL) JR Z,L2 LD A,(SUBPPC) INC A LD (HL),A LD HL,(PPC) LD (NEWPPC),HL ; ; now we clear a couple of things ; which would ordinarily be ; cleared... ; L2 LD HL,0 LD A,H LD (FLAGX),A LD (DEFADD),HL ; ; finally, the address of our ; error will have been popped ; from the stack; so we put it ; back (remember, we stored it in ; an unused location)... ; LD HL, (23728) PUSH HL ; ; now we jump back into the ; interpreter, as if CONTINUE had ; inst been entered, but after ; the check for BREAK... ; LD HL,(NEWPPC) JP 1B9EH