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