I used to wonder why different versions of Basic on 8bit machines would impose different limits on the highest line number permitted.

I should point out this excludes any trickery to manually change a line number to an otherwise inaccepted value ( line 0 or 10000 in ZXBasic for example) yes I am well aware and used to use such tweaks myself :D It would be off question to go into it being stored twice anyway.

From my memory Locomotive Basic as used on the Amstrad CPC machines accepts up to 65535 which is logical as for storing a number > 255 one would usually use two bytes, a low and high byte.

This brings me onto the question itself , BBC Basic on the Model A and B at least are limited to 32767 and ZxBasic is limited to 9999. I have not looked into what other platforms limit this as and I am not asking for a list :)

Question really is why impose these ( what appear to be ) artificial limits when they are if I am correct stored as two bytes anyway giving a range of up to 65535 ?

I cannot fathom any likely design reason for it and given the variances in displays between platforms in general it is nothing to do with neatness, besides Basic statements spill quite messily anyway it's part of it!

  • 3
    Some basics saved the line number as an ASCII string, so that could explain 4 digit maximum. Using max 32767 could be using signed integer of some reason, or the top bit was used by the interpreter/editor for marking purposes – UncleBod Jan 14 at 12:43
  • I was not aware of storing it as a string , useful to know ! Thank you. – AndyF Jan 14 at 12:59
  • Will look into which versions employ strings for this , logic tells me early variants. – AndyF Jan 14 at 13:21
  • 2
    According the ZX Spectrum Manual, the line number is not stored as a string, see: worldofspectrum.org/ZXBasicManual/chap24diag3.gif – Martin Maly Jan 14 at 13:37
  • 5
    oric basic accepts 63999 but not 64000 as a line number... – Jean-François Fabre Jan 14 at 22:53

The answer is pretty straightforward:

  • 65535 is for BASICs, which can handle number lines as an unsigned integer (2 bytes wide)
  • BASICs, which handles two-byte integers as "signed", usually have the line number limit 32767 (highest positive number). Those BASICs often have the "negative addresses" for POKEs and PEEKs, i.e. "POKE -1247,10" etc.
  • Sinclair ZX BASIC has the "4 digit limitation" due to the formatting reasons when listing on the screen. The line numbers are aligned to the right, so the cursor character ">" is always at position 5... See:

ZX Spectrum listing

In the first two cases, it is the consequence of internal number handling. ZX Spectrum has a minimalistic approach, so the "4 digit" is, in my opinion, a fair trade-off between the lines count and line length...

| improve this answer | |
  • Perfect thanks. Some of the ZX design reasons do not make logical sense to me however the answer is fully comprehensive enough for me. – AndyF Jan 14 at 13:00
  • 1
    I think many MS versions of basic use the high byte of the line number to distinguish immediate mode (255 == immediate mode), limiting line numbers to 0xFEFF (64279). – supercat Jan 15 at 21:19
  • 1
    Correct but incomplete. It doesn't explain Commodore 64 BASIC (0 to 63999), or GW-BASIC (0 to 65529) for example. – Selcuk Jan 16 at 1:11
  • 2
    "No one will ever write a 10,000 line program." – bishop Jan 16 at 17:24

With so many different implementations of BASIC a comprehensive answer is difficult. So here's the limits for TRS-80 Model I and III BASIC (written by Microsoft).

Line numbers are stored as a two byte word but the largest allowed by the input routines is 65529. Primarily because this is an easier limit to test rather than checking for overflow. The line number is converted from ASCII to binary a character at a time using a pretty standard algorithm. Start with a 16 bit value line = 0. For each digit multiply line by 10 and add the digit to line.

To check if the line number is acceptable, compare line against 6552 before multiplying it by 10. This will guarantee the value is <= 65529 because a digit can add only 9 at most.

The Model I/III processor is a Z-80 which has no hardware multiply instruction. Checking for carry after each step in the multiply by 10 code would require 4 branch instructions (and one after the digit add) whereas the comparison as written is only one. ROM space was at a premium so losing a few line numbers was worth the space savings.

This BASIC also reserves some line numbers for special purposes. It tracks a current line number when running the program but uses a current line number of $FFFF (65535) to indicate "direct" mode (i.e., at the READY prompt).

$FFFE (65534) triggers a reboot in the error message routine. This is only used at startup when the ROM asks Memory Size? allowing the user to set the top of available memory. If an address too low or too high or an invalid number is entered the error routine is called which must reboot since BASIC hasn't been fully initialized.

| improve this answer | |
  • 2
    I had a TRS-80 (or, more accurately, the Video Genie clone of it) and had something like the number 65529 floating around my head when I read the question. According to [Microsoft Basic Decoded [...] for the TRS-80](doc.lagout.org/science/0_Computer%20Science/…) [PDF, 1.5MB], comments on pages 193 and 199 (195 and 201 of the PDF) suggest 65534 is the "Initial BASIC line number", part of the IPL (initial Program Loader). [cont] – TripeHound Jan 15 at 10:28
  • 2
    [cont] As far as I can see (if I'm reading the code at 1A09 on page 199/201 correctly), if a STOP/END on line 65534 is encountered, the BASIC interpreter jumps to the IPL entry-point in the ROM. Not sure whether this is "simply" part of the power-on sequence: address 1919 [in ROM, copied to 40A2 during IPL] on page 193/195 holds "line number 65534", and the next address [191B ROM, copied to 40A4] is the "PST" where tokenised BASIC is held. See also "Reset Processing (non-disk)" on page 13 (15 in PDF) or a way for a BASIC program to "reset" things on exit. – TripeHound Jan 15 at 10:51
  • @TripeHound Good work! Appears that its sole purpose is to errors in Memory Size? input. Updating answer... – George Phillips Jan 15 at 18:15

On the original Dartmouth Time-Sharing BASIC (circa 1964), the maximum line number was 99999.

Dartmouth Time-Sharing ran on a hybrid Datanet-30 / GE 235 system. The Datanet-30 could communicate with up to 128 terminals at once, and handled the I/O. The GE 235 was better at computation and was responsible for executing the BASIC programs.

99999+1 was the largest power of 10 that could be stored in the Datanet-30's 18-bit words.

| improve this answer | |
  • 5
    I think this answer is to the point. The question seems to have an implicit assumption that an implementation 'should' use the maximum number possible under some chosen hardware representation. However, the 'B' in 'BASIC' suggests to me that a better-off choice is based in user considerations, and a limit of 99999 is thus more sensible (easier to explain to users) than say 131071 would be. – another-dave Jan 15 at 12:49

BBC BASIC V, as used on the Acorn Archimedes, had a maximum line number of 65279 according to Matt Godbolt's analysis of the tokenised file format.

Each line is stored as a sequence of bytes:
0x0d [line num hi] [line num lo] [line len] [data...]
The line number is as you’d expect — the line number — with one exception. The maximum line number is 65279 (0xfeff) as the special marker 0x0d 0xff is used to signify the end of the program. The line length includes the three preceding bytes, making the maximum length of a line 251 bytes.

In the 8-bit versions of BBC BASIC (checked on a BBC B and BBC Master emulator), the maximum line number that can be entered at the prompt is 32767. Higher numbers result in Syntax error.

| improve this answer | |

I have actually looked into this in some depth. All major variations of BASIC that I can find source for store the line number as an int.

This includes even Tiny BASIC, which used a single unsigned byte, as one could not type a program with 255 lines into their target machines (4k total memory) anyway. All others that I have looked at - Altair, MS 6502, Atari and BBC all used a 16-bit int.

In Tiny, the only parsing completed on the line at edit time was the line number. All of the rest of the line was left in its original text format. MS parsed the number and the first token of every statement, the rest text. Atari parsed the entire line into tokens - I can't recall what BBC did.

Almost all BASICs reserved one line to indicate "immediate mode", lines entered without a number. This was often 0 or -1, although I recall others being used as well. This often resulted in two lines being set aside, -1 and zero being illegal in the parser.

Atari used a signed int and made everything -ve as immediate mode. In practice, you can only have a single immediate mode line, so that was -1 (or as in some books, 32678). Zero was allowed. I'm not sure why they did this, as there was no 16-bit math package or such, and using 0 or FFFF for immediate seems to be a better solution.

I have written a BASIC parser in lex/yacc with the express intent of checking what ranges programs actually use.

| improve this answer | |
  • Why do you need a parser to check the range used? Can't you just look at the last line of the file? – another-dave Jan 16 at 2:20
  • You still have to parse the number :-) It's all regex in the end. – Maury Markowitz Jan 16 at 15:06

According to Z BASIC Interactive BASIC Compiler [170 page, 2MB PDF] (or this 772 page, 32MB version, from which quotes below are taken), the Z BASIC Interpreter (which seemed to be available for MS-DOS, APPLE, Macintosh, CP/M and TRS-80 Models 1,3 and 4), has a maximum line number of 65,534 (and the minimum is 0):

The Standard Line Editor requires each line of a program to have a line number for editing and reference purposes (labels are available too.) Line numbers may range from 0-65534. Each line can be up to 250 characters long

p14 (16 of PDF)

Although it may have other uses, line number 65,535 seems to be reserved for nuances in error-handling:

ON ERROR statement

Enable user disk error trapping. Errors are returned using the ERROR function. You must check for errors---ZBasic will not when this parameter is set.

If a disk error occurs the program does a GOSUB to the line or label specified.

Disable user disk error trapping. ZBasic will trap the disk errors and give error messages at runtime.

p283 (285 of PDF)

The ON ERROR GOSUB 65535 variant seems to be similar to ON ERROR RESUME NEXT in Visual Basic, meaning: "don't complain, I'll check the error-code myself (if I can be bothered)".

| improve this answer | |
  • Thanks. Agree ON ERROR is very useful when combined with a check of the code number too so you can decide how to handle it. – AndyF Jan 15 at 12:06

Donald Alcock's, who treats "the need for portability as an axiom", wrote in Illustrating BASIC (Cambridge University Press, 1977):

The first line number in a program must be greater than 0. There is always a limit to the highest line number: some BASICs stop at 9999, so it is best to accept this as the limit.

| improve this answer | |

I tested that with an emulator and it appears that the Oric basic (coded Microsoft) accepts lines from 0 to 63999

Trying to create a line number 64000 (hex 0xFA00) results in a syntax error.

The Oric Atmos manual confirms this on page 15:

The line number may be any integer (whole number) up to 63999

Some comments in the Oric disassembled rom seem to indicate that high byte 0xFF is reserved for in-line mode:

C4A0 A4 A9 LDY $A9 If high byte of line number
C4A2 C8 INY is #FF then the computer is in
C4A3 F0 03 BEQ $C4A8 immediate mode (not program).

also here:

C4C7 A2 FF LDX #$FF Set immediate mode
C4C9 86 A9 STX $A9

Clearly this limits to maximum 0xFE00 (65024). But this 64000 thing is probably clearer to remember from an user point of view than 65024. Also easier to test (only MSB to check against) and a multiple of 1000.

The part that checks for that limit is probably here:

CAF2 C9 19 CMP #$19 Syntax error if MSB is over
CAF4 B0 D4 BCS $CACA 25 - result will be too big.
CAF6 A5 33 LDA $33 Multiply original number by
CAF8 0A ASL A 10, firstly adding itself to
CAF9 26 91 ROL $91 4 times itself to give 5 times
CAFB 0A ASL A itself. Then double result.

as 0x1900 is 6400 and then value is multiplied by 10.

Note that those properties (direct mode & multiplication by 10) are very similar to TRS-80 Microsoft basic as exposed in another answer.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.