Example program in BBC BASIC's assembler
We present here a short example program in BASIC. The error handler copes with pre-emption, responding to RC_QUIT by calling BASIC's own error handler. This will not close files, filters wildcards, or memory however, so if you use these features you must modify the error handler to close these things first before calling BASIC. The program here does something which BASIC cannot normally do, which is to read the update date of a file. When the program is run it assembles the code and asks for a filename. It attempts to open the file for DOR access, indicating failure with a system error box, and then reads the update date. Finally, having released the DOR handle, the program displays the explicit filename, expanded by GN_Opf, and the update date.
This listing can be 'loaded' by CLI. Copy this source code as save as text file as 'example.bas' on your desktop, then upload to :RAM.0 on your Z88. Start BBC BASIC application, execute command *CLI .*:RAM.0/example.bas
to "type it in". Finally, RUN
.
.J AUTO DIM code 512 : REM space for program GN_Esp=&4C09 : REM return pointer to system error message GN_Soe=&3C09 : REM Write string at extended address to standard output GN_Nln=&2E09 : REM carriage return, linefeed to std. output GN_Sop=&3A09 : REM output string to std. output GN_Opf=&6009 : REM open file OS_Erh=&75 : REM install error handler OS_Esc=&6F : REM examine special condition GN_Err=&4A09 : REM standard system error box GN_Sdo=&0E09 : REM date and time to standard output OS_Dor=&87 : REM DOR interface dr_rd=&09 : REM read DOR record dr_fre=&05 : REM free DOR handle op_dor=&06 : REM open file for DOR access rc_quit=&67 : REM KILL request error code rc_esc=&01 : REM escape detection error code FOR pass=0 TO 2 STEP 2 P%=code [ OPT pass LD HL,0 ADD HL,SP \ get current BASIC stack pointer LD (bstk),HL \ preserve it LD SP,(&1FFE) \ install system (safe) stack pointer XOR A LD B,A LD HL,errhan \ address of error handler OPT FNsys(OS_Erh) \ install new error handler LD (obou),A \ save old error handler call level LD (oerr),HL \ save old error handler address \ Here is the call to your assembler language routine which should be \ included at the end of this code. CALL main \ call main routine .exit LD HL,(oerr) \ address of old error handler LD A,(obou) \ old call level LD B,0 OPT FNsys(OS_Erh) \ restore previous error handler LD SP,(bstk) \ restore BASIC stack pointer RET \ return to BBC BASIC interpreter .errhan RET Z CP rc_esc \ ESC pressed? JR NZ,err1 OPT FNsys(OS_Esc) \ acknowledge ESC LD A,rc_esc OR A \ return rc_esc back to main program RET \ Fc = 0, Fz = 0 .err1 CP rc_quit \ KILL request? JR NZ,err2 LD HL,(oerr) \ re-install old error handler LD A,(obou) \ old call level OPT FNsys(OS_Erh) LD SP,(bstk) \ install BASIC stack pointer LD HL,(oerr) LD A, rc_quit \ reload A with RC_QUIT OR A \ Fz = 0 SCF \ Fc = 1 JP (HL) \ jump to BASIC's error handler .err2 \ write error message if possible OPT FNsys(GN_Esp) \ Get ext. pointer to system error message OPT FNsys(GN_Soe) \ Write error message to std. output OPT FNsys(GN_Nln) \ New line to std. output OR A \ Fc = 0 RET .bstk DEFW 0 \ storage for BASIC stack pointer .obou DEFB 0 \ storage for old call level .oerr DEFW 0 \ storage for old error handler address \ ---------------------------------------------------------------------- \ main routine starts here .main LD HL,scratch_1 \ holds address of file to open LD DE,scratch_2 \ explicit name buffer LD C,40 \ size of explicit name buffer LD B,0 \ HL string pointer is local LD a, op_dor \ get DOR handle OPT FNsys(GN_Opf) \ open... JR NC,opened_OK OPT FNsys(GN_Err) \ report error in standard window RET .opened_OK LD A,dr_rd \ read DOR record LD B,ASC"U" \ read update information LD C,6 \ 3 byte internal date, 3 byte int. time LD DE,scratch_1 \ store returned information at (DE) OPT FNsys(OS_Dor) \ fetch update date LD A,dr_fre OPT FNsys(OS_Dor) \ free DOR handle LD HL,scratch_2 \ display explicit filename OPT FNsys(GN_Sop) \ to standard output LD HL,tab_str OPT FNsys(GN_Sop) \ tab to column 40 LD HL,scratch_1 OPT FNsys(GN_Sdo) \ output returned update date OPT FNsys(GN_Nln) \ display newline RET \ back to BASIC .scratch_1 DEFM STRING$(40,"X") .scratch_2 DEFM STRING$(40,"X") .tab_str DEFM CHR$1+"2X"+CHR$(32+40)+CHR$0 \ main routine ends here \ ---------------------------------------------------------------------- ] NEXT pass CLS PRINT "Read File Update Date and Time" INPUT "Filename:"A$ IF LEN(A$)>40 THEN PRINT "String too long": END A$=A$+CHR$0 : REM null-terminate filename string $scratch_1=A$ CALL code END : DEF FNsys(arg) IF arg>255 THEN PROC_Rst20Defw(arg) ELSE PROC_Rst20Defb(arg) =pass : DEF PROC_Rst20Defw(arg) [OPT pass RST &20: DEFW arg ] ENDPROC DEF PROC_Rst20Defb(arg) [OPT pass RST &20: DEFB arg ] ENDPROC