Acorn BBC BASIC II Memory Map

← Acorn BBC BASIC

Addresses outside the ROM used by Acorn BBC BASIC II at run time — zero-page workspace, RAM buffers, and memory-mapped I/O. For the ROM code itself (&8000&BFFF), see the disassembly listing.

Zero page

Address Name Access Description
&0000–&0001 zp_lomem R/W

LOMEM: the start of variable storage. Defaults to TOP when a program is run and grows upward as variables are created (tracked by VARTOP); settable with LOMEM=.

&0002–&0003 zp_vartop R/W

VARTOP: the address just past the last allocated variable — where the next new variable goes. Runs from LOMEM up toward zp_stack_ptr; the two meeting is "No room".

&0004–&0005 zp_stack_ptr R/W

Pointer to the top of BASIC's value stack, which grows downward from HIMEM. The stack carries expression temporaries, strings pushed during evaluation, and — across a PROC/FN call — a saved copy of the 6502 hardware stack. "No room" is raised if it descends to meet VARTOP.

&0006–&0007 zp_himem R/W

HIMEM: the top of memory available to BASIC. The value stack (zp_stack_ptr) grows down from here; settable with HIMEM=. Read from the MOS (OSBYTE &84) at startup.

&0008–&0009 zp_erl R

ERL: the line number in which the last error occurred, set by the error handler and read by the ERL function (0 in immediate mode).

&000A zp_text_ptr_off R/W

PtrA offset: the offset of the next character within the program line addressed by zp_text_ptr. The interpreter reads the tokenised program through this pointer/offset pair.

&000B–&000C zp_text_ptr R/W

PtrA: the primary program/text pointer — the base address of the line currently being interpreted. Combined with zp_text_ptr_off to fetch tokens.

&000D–&0011 zp_rnd_seed R/W

RND state: the 33-bit linear-feedback shift register behind RND. &0D-&10 are a little-endian 32-bit value (bits 0-31); bit 0 of &11 is bit 32. Advanced 32 steps per RND call; reseeded by RND(-n).

&0012–&0013 zp_top R/W

TOP: the address just past the end of the tokenised program text (and the default for LOMEM). Read by the TOP pseudo-variable and set when the program is edited.

&0014 zp_print_bytes R/W

Print field width: the @%-derived field width used while formatting a number for PRINT, counting the characters emitted so far in the current field.

&0015 zp_print_flag R/W

Number-base flag for output: 0 selects decimal, negative selects hexadecimal (set by STR$~ and PRINT ~).

&0016–&0017 zp_error_vec R/W

ON ERROR handler address: where the interpreter jumps when an error is trapped. Reset to the default handler (&B433) at the start of each statement line; set by ON ERROR.

&0018 zp_page R

PAGE high byte: the start of the BASIC program as a page number (PAGE = this × 256). Read from OSHWM at startup; the PAGE pseudo-variable exposes it.

&0019–&001A zp_text_ptr2 R/W

PtrB: the secondary text pointer, used by the expression evaluator and the tokeniser while zp_text_ptr (PtrA) is preserved. Paired with zp_text_ptr2_off.

&001B zp_text_ptr2_off R/W

PtrB offset: the offset of the next character for the secondary text pointer zp_text_ptr2.

&001C–&001D zp_data_ptr R/W

DATA pointer: the address of the next DATA item to be READ. Set to the program start by RESTORE (or a line by RESTORE n) and advanced as items are read.

&001E zp_count R/W

COUNT: the number of characters printed since the last newline (the print column). Used for , field alignment and the WIDTH auto-newline; read by the COUNT function.

&001F zp_listo R/W

LISTO flags: the listing-indent options set by LISTO n. Control whether LIST indents FOR/REPEAT bodies and spaces tokens.

&0020 zp_trace_flag R/W

TRACE flag: &00 = tracing off, &FF = on (TRACE ON/TRACE OFF). When on, executed line numbers are printed in brackets up to zp_trace_max.

&0021–&0022 zp_trace_max R/W

TRACE ceiling: the highest line number that TRACE reports (TRACE n). Lines above it are not traced.

&0023 zp_width R/W

WIDTH: the print line width for the auto-newline (WIDTH n). &FF (the default) means no automatic wrap; compared against zp_count.

&0024 zp_repeat_level R/W

REPEAT stack depth: how many REPEAT loops are open, indexing repeat_stack. Not saved across a PROC/FN call, so leaving a loop via ENDPROC/GOTO leaks its entry.

&0025 zp_gosub_level R/W

GOSUB stack depth: how many GOSUB calls are open, indexing gosub_stack. Not saved across a PROC/FN call.

&0026 zp_for_level R/W

FOR stack depth: how many FOR loops are open (×15 gives the byte offset into for_stack). Not saved across a PROC/FN call.

&0027 zp_var_type R/W

Value type of the most recently fetched/evaluated value: 0 = string, positive (&40) = integer, negative = real. Drives the type dispatch throughout the evaluator.

&0028 zp_opt_flag R/W

Inline-assembler OPT flags (OPT n): bit 0 prints a listing, bit 1 enables error reporting, bit 2 assembles to the offset address O% instead of P%. &FF outside [ ] marks "not assembling".

&0029 zp_asm_opcode R/W

Inline assembler: the opcode byte being built for the instruction currently being assembled, before its operand bytes are appended.

&002A–&002D zp_iwa R/W

IWA — the 32-bit integer work accumulator. Holds the integer operand/result of the evaluator and the integer arithmetic primitives, and doubles as a pointer to a variable’s value during a fetch.

&002E–&0035 zp_fwa_sign R/W

FWA — floating-point work accumulator A (&2E-&35): sign (&2E), overflow/guard (&2F), excess-128 exponent (&30), 32-bit mantissa MSB-first (&31-&34) and a rounding byte (&35). The main register for real arithmetic; see zp_fwb_sign.

&0036 zp_strbuf_len R/W

Length of the string currently in the string work area at string_work.

&0037–&0038 zp_general R/W

General-purpose work pointer (&37-&3A). Reused widely — the tokeniser/line scanner, the variable-chain walk, the program editor — as a scratch 16-bit pointer.

&0039–&003A zp_fileblk R/W

Filing-system control block (&39 onward): the OSFILE / load-save parameter block. Filing is not active during arithmetic, so this overlaps the FP workspace below (zp_fwb_sign onward).

&003B–&0042 zp_fwb_sign R/W

FWB — floating-point work accumulator B (&3B-&42), same layout as zp_fwa_sign. Supplies the second operand for binary floating-point operations (add, multiply, divide).

&0043–&0047 zp_fp_temp R/W

Floating-point temporary / scratch (&43-&47). Holds spill bytes for the FP routines and serves as the quotient build area for integer DIV/MOD.

&0048 zp_dp_flag R/W

Decimal-point-seen flag, set while parsing a number literal so a second . is rejected and the fractional digits are scaled.

&0049 zp_dec_exp R/W

Decimal exponent accumulated while parsing the E part of a real literal.

&004A zp_int_exp R/W

Integer-part / exponent scratch: holds the integer exponent during number parsing and the integer part of a value in EXP and the int/fraction split.

&004B–&004C zp_fp_ptr R/W

Pointer to a packed 5-byte floating-point value (a variable or an FP temporary) for the pack/unpack routines.

&004D–&004E zp_coeff_ptr R/W

Pointer to the current coefficient table, used while evaluating the continued-fraction approximations in the trig functions.

&00FD–&00FE zp_error_ptr R/W

Pointer to the error block currently being reported (the bytes after a BRK): the error number and message the handler is processing.

&00FF zp_escflg R/W

ESCFLG — the MOS escape flag. Its top bit is set when Escape is pressed; BASIC polls it between statements, acknowledges it via OSBYTE, and raises the "Escape" error.

Other

Address Name Access Description
&003C zp_fwb_ovf

FWB overflow byte (&3C), part of zp_fwb_sign. A much-reused scratch location: outside floating point it serves as the tokeniser's line-number-arming flag (&FF after GOTO etc. means encode the next number as a line number), a variable-chain walk pointer, an array dimension-descriptor offset, and LIST's REPEAT/UNTIL indent counter. Read each use in its own context rather than assuming a single global meaning.

6502 hardware stack

Address Name Access Description
&0100–&01FF hw_stack R/W

The 6502 hardware stack (page 1), used normally for JSR/RTS and register saves. A PROC/FN call copies a snapshot of the live stack onto the BASIC value stack and restores it on return, so call nesting is bounded by free stack space rather than a fixed table.

Resident integers & FP workspace

Address Name Access Description
&0400–&046B resint_at R/W

The resident integer variables, four bytes each: @% here at &0400, then A%-Z% at &0404-&046B. @% sets the PRINT/STR$ number format. Two slots double as the inline assembler's counters — O% (the 'O' slot, &043C) is the offset-assembly address and P% (the 'P' slot, &0440) the program counter.

&046C–&047F fp_temp1 R/W

Four 5-byte packed floating-point temporaries: TEMP1 (&046C), TEMP2 (&0471), TEMP3 (&0476) and TEMP4 (&047B). The maths routines stash intermediate reals here while reusing FWA / FWB.

&0480–&04FF var_ptr_table R/W

The dynamic-variable chain-head table: a two-byte head pointer per initial-character class (A-Z, a-z, _, @), addressed as &0400 + 2×char. find_variable walks the linked list of variables sharing an initial character; create_variable links a new one in at the head.

String and line buffers

Address Name Access Description
&0600–&06FF string_work R/W

The string work area / CALL parameter block. BASIC builds string results here — the text of STR$, the digits of a number conversion, a popped string for comparison — with the length in zp_strbuf_len. CALL also assembles its parameter block here.

&0700–&07FF line_input_buf R/W

The line input buffer. The line editor reads a typed line (at the > prompt or for INPUT) into here via OSWORD 0; the tokeniser then processes it in place.

Index bases

Addresses used only as an indexing base — the operand names a base and the byte actually touched is base + X (or + Y), where the index register is a caller-supplied offset, never zero. The literal byte at the base address is never read or written, so these are documented here rather than on the memory map: they are bases, not locations the ROM owns.

Other

Base Name Description
&0106 frame_local_count
&047F var_table_base
&04F1 for_var_lo
&04F2 for_var_hi
&04F3 for_type
&04F4 for_step0
&04F5 for_step1
&04F6 for_step2
&04F7 for_step3
&04F9 for_limit0
&04FA for_limit1
&04FB for_limit2
&04FC for_limit3
&04FE for_loopback_lo
&04FF for_loopback_hi
&0501 for_set_ptr_hi
&0502 for_set_type
&0503 for_set_step0
&0504 for_set_step1
&0505 for_set_step2
&0506 for_set_step3
&0508 for_set_limit0
&0509 for_set_limit1
&050A for_set_limit2
&050B for_set_limit3
&050D for_set_loop_lo
&050E for_set_loop_hi
&05A3 repeat_loop_lo
&05B7 repeat_loop_hi
&05CB gosub_return_lo
&05E5 gosub_return_hi
&05FF strbuf_base

FOR / REPEAT / GOSUB stacks

Base Name Description
&0500 for_stack

The FOR stack: up to 10 frames of 15 bytes each (&0500-&0595; depth in zp_for_level). Each frame holds the control-variable address and type, the STEP and limit values, and the loop-back text pointer — pushed by FOR, consulted and updated by NEXT.

&05A4 repeat_stack

REPEAT loop-start text pointers, low bytes — up to 20 nested (depth in zp_repeat_level); high bytes in repeat_stack_hi. UNTIL reloads the pointer to re-test its condition.

&05B8 repeat_stack_hi

High bytes of the REPEAT loop-start pointers; low bytes in repeat_stack.

&05CC gosub_stack

GOSUB return text pointers, low bytes — up to 26 nested (depth in zp_gosub_level); high bytes in gosub_stack_hi. RETURN pops the top entry.

&05E6 gosub_stack_hi

High bytes of the GOSUB return pointers; low bytes in gosub_stack.