11

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!

6
  • 4
    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, 2020 at 12:43
  • I was not aware of storing it as a string , useful to know ! Thank you.
    – AndyF
    Jan 14, 2020 at 12:59
  • Will look into which versions employ strings for this , logic tells me early variants.
    – AndyF
    Jan 14, 2020 at 13:21
  • 2
    According the ZX Spectrum Manual, the line number is not stored as a string, see: worldofspectrum.org/ZXBasicManual/chap24diag3.gif Jan 14, 2020 at 13:37
  • 5
    oric basic accepts 63999 but not 64000 as a line number... Jan 14, 2020 at 22:53

8 Answers 8

24

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...

5
  • 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, 2020 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, 2020 at 21:19
  • 2
    Correct but incomplete. It doesn't explain Commodore 64 BASIC (0 to 63999), or GW-BASIC (0 to 65529) for example.
    – Selcuk
    Jan 16, 2020 at 1:11
  • 2
    "No one will ever write a 10,000 line program."
    – bishop
    Jan 16, 2020 at 17:24
  • To answer @Selcuk, supercat has the right idea. GW BASIC's limit of 65529 was the same as several other BASICs Microsoft created, such as for the TRS-80 line of computers. The reason was that lines 65530 to 65535 were "reserved for system use." For example, the TRS-80 Model I Level 2 BASIC Language Reference states that "65535 is used internally to store a line entered directly without a line number."
    – hackerb9
    Aug 24, 2022 at 21:11
20

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.

3
  • 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, 2020 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, 2020 at 10:51
  • @TripeHound Good work! Appears that its sole purpose is to errors in Memory Size? input. Updating answer... Jan 15, 2020 at 18:15
13

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.

1
  • 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.
    – dave
    Jan 15, 2020 at 12:49
7

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.

8
  • Why do you need a parser to check the range used? Can't you just look at the last line of the file?
    – dave
    Jan 16, 2020 at 2:20
  • You still have to parse the number :-) It's all regex in the end. Jan 16, 2020 at 15:06
  • While BBC BASIC did accept 0 as a line number, an error at line 0 would be reported with the "at line 0" omitted as if it were an immediate mode error. Oct 21, 2020 at 10:30
  • Do you have a link to your lex/yacc code and the results? I'm curious what the maximums were and what the "reserved for system use" line numbers were used for on various machines. (Also, does "-ve" mean "negative"? You may want to change that in your answer as it was confusing.)
    – hackerb9
    Aug 24, 2022 at 21:23
  • Your question about Atari's BASIC using signed numbers makes me wonder if it might share lineage with VAX BASIC which also had a max of 32767. According to Wikipedia, VAX BASIC was based on DEC's BASIC-PLUS for the PDP-11 from 1972. DEC's manual ( archive.org/details/…) states the max line number is 32767.
    – hackerb9
    Aug 24, 2022 at 21:29
6

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.

1
  • 1
    That is correct, but there is a second and more complex format used when a line number is the target of a GOTO or GOSUB. This is the "line number" token (&8D) followed by the number encoded into three bytes such that none of them are >= &80. (This is done so that they cannot be confused with legitimate tokens, and is an optimisation for scanning through lines at run time eg when looking for the ELSE in an IF...THEN statement.)
    – lob
    Jan 10, 2021 at 21:08
4

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

ON ERROR GOSUB 65535
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.

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

ON ERROR RETURN
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)".

1
  • 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, 2020 at 12:06
3

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.

1
  • Many mainframe and mini BASICs used BCD math and encoded line numbers in decimal format. This you often see 9999 or 49999 or similar as the upper limit. Micros almost always used 16 bit ints for line numbers, even those that did use BCD math, like Atari. Aug 26, 2022 at 12:14
2

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .