RUNTIME

RUNTIME: the library compiled programs call

What it is

RUNTIME is 4013 bytes of 6502 machine language, normally loaded at $0803-$17AF with BLOAD RUNTIME before a compiled program is run with BRUN. Compiled code is mostly calls: almost every statement, operator and function becomes a JSR into RUNTIME or into the Applesoft ROM, after code that loads the operands. RUNTIME keeps everything the ROM does not provide: integer arithmetic, the variable dispatchers, arrays, FOR/NEXT, the string routines and garbage collector, INPUT and READ, COMMON, ONERR/RESUME, and small entries that check an argument and go on into the ROM's own code for a statement.

The source is written for Apple's DOS Toolkit assembler (EDASM) and assembles to the library byte for byte. It is split into files small enough for the editor; RUNTIME.S1 holds the equates and the ORG, and each file ends with CHN and the name of the next, so assembling RUNTIME.S1 assembles the whole library (see Source files).

To assemble it with the DOS Tool Kit: boot the Tool Kit disk with the source disk in drive 2, RUN EDASM, then at the editor's : prompt type DRIVE 2 and ASM RUNTIME.S1. The assembler reports SUCCESSFUL ASSEMBLY: NO ERRORS and writes RUNTIME.S1.OBJ0, a binary file at $0803 of 4013 bytes, identical to RUNTIME. (The source disk has room for it; rename it RUNTIME to use it.)

Starting a program

Every object file starts with JSR INIT and a 17-byte header (INIT). INIT:

How compiled code calls it

Accumulators. Real values are in Applesoft's FAC ($9D-$A2), with ARG ($A5-$AA) as the second operand. Integers are in IACC ($A0 high, $A1 low; these are FAC+3 and FAC+4, which is where AYINT leaves its result) and IARG ($9E/$9F). Strings are pointers to [length][text]: the loaded string at $77/$78 and the pushed string at $79/$7A.

Real and integer entries. A routine that takes a number usually has two entries 3 bytes apart. The real entry is JSR AYINT (or for an address JSR $58, which floats IACC), and the code generator uses whichever matches the operand's type. Byte arguments go through the ROM's CONINT (error ILLEGAL QUANTITY above 255); addresses through GETADR.

Inline operands. Some calls are followed by data the routine reads through its return address and then returns past: the loop variable's address after the loop start and NEXT; a literal's address after STRLIT; the handler's address after ONERR; a count and line addresses after ON GOTO/GOSUB; an array's descriptor after the array dispatchers.

Variables. Compiled code reaches every variable through a small routine of its own, which loads an operation number and the variable's address and jumps to a dispatcher:

DispatcherOperations
DISPREAL real0 load FAC, 1 store, 2 add, 3 variable - FAC, 4 multiply, 5 compare, 6 load ARG, 7 variable / FAC
DISPINT integer0 load IACC, 1 store, 2 add, 3 variable - IACC, 4 multiply, 5 compare; 6-13 the real operations with the variable used as a real
DISPSTR stringload (carry set) or store (carry clear) the string pointer
ARRREAL, ARRSTR, ARRINT arraysload an element (carry set) or leave its address for ARRSTORE (carry clear)

Memory and strings

String space runs down from HIMEM; $6F/$70 is its bottom. New strings are made below it (NEWSTR); when there is no room the garbage collector (GARBAG) packs the strings still in use at the top. Its roots are the COMMON strings, the local strings and the two string accumulators; literals and DATA items stay where they are in the program. An empty string is kept at HIMEM-1, and cleared string variables point at it. REM! CLEAR CHAIN (CLRCHAIN) collects garbage keeping only the COMMON strings, then clears the locals, ready for BRUN of the next program.

FOR loops

The loop start stores the initial value and pushes the variable's address; the limit and step push the rest. A frame is 16 bytes, from the top of the stack:

BytesReal loopInteger loop
1-2the marker $09B0the marker
3-4loop address - 1byte 4 = 0 marks an integer loop
5-9step (packed real)step in 5-6
10-14limit (packed real)loop address in 8-9, limit in 10-11
15-16the variable's addressthe variable's address

The marker is also a valid return address: a subroutine that RETURNs with loops still open lands at FORUNWND, which drops the frame and returns again. NEXT finds the variable's frame, dropping inner loops, adds the step and compares with the limit in the step's direction. POP passes over frames to drop a GOSUB return.

Errors

Every error ends at ERREXIT with Applesoft's error number in X. Without ONERR the object address of the failing call becomes the "line number" of the message, so errors report addresses in the compiled program. With ONERR the patched CHRGET passes control to the handler, and RESUME (with the RESUME/debug option, which puts DEBUG before every statement) restarts the failing statement.

NumberErrorRaised by
0NEXT WITHOUT FORNEXT
16SYNTAXREAD of a bad number
22RETURN WITHOUT GOSUBPOP, RETURN on an empty stack
42OUT OF DATAREAD
53ILLEGAL QUANTITYhi-res coordinates, shape number, ASC, LEFT$/RIGHT$/MID$ count, byte arguments
69OVERFLOWinteger arithmetic, integer loops
77OUT OF MEMORYstrings, CLEAR, HIMEM:
107BAD SUBSCRIPTarray elements
163TYPE MISMATCHa USECOMMON program whose COMMON block differs
176STRING TOO LONGconcatenation
254, 255bad input, Control-CINPUT (with ONERR)

Entries by kind

KindEntries
programINIT, PGMEND, STOP, DEBUG, ONERR, RESUME, CLRCOM, CLEAR, CLRCHAIN, HIMEM
flowPOP, ONGOTO, ONGOSUB, FORINIT, NEXT, FORLIM, FORSTEP
integersDISPINT, INEG, ISUBT, IMOVE, FLOATI, LOGORI, LOGANDI
relationsRELNE, RELGT, RELGE, RELEQ, RELLE, RELLT, STRGE, STRLT, STRLE, STRGT, STREQ, STRNE
stringsDISPSTR, STRLIT, PRSTR, CONCAT, PUSHSTR, CHRFN, STRFN, LEFT, RIGHT, MID2, MID3, VALFN, ASCFN, LENFN, FREFN
input and outputINPBEG, INPNUM, INPSTR, INPEND, READNUM, READSTR, RESTORE, GETNUM, GETSTR, PRINTN, COMMA, TAB, SPC, PRNUM, INNUM
screen and graphicsVTAB, HTAB, COLOR, PLOT, HLIN, VLIN, SCRN, HCOLOR, HPLOT, HPLOTTO, DRAW, XDRAW, DRAWAT, XDRAWAT, ROT, SCALE, PDL, POS
memorySVADDR, PEEK, CALL, POKE, WAIT, WAIT3, SPEED
arraysARRREAL, ARRSTR, ARRINT, ARRSTORE, PUSHSUB

Source files

FileAddressesCharacters
RUNTIME.S1$0803-$08DA10969
RUNTIME.S2$08DB-$0B109988
RUNTIME.S3$0B11-$0E3311854
RUNTIME.S4$0E34-$119112045
RUNTIME.S5$1192-$14FC12014
RUNTIME.S6$14FD-$17AF9506