Skip to content

Microsoft BASIC reference ​

Every command, function and operator in Altair 8K BASIC, the version of Microsoft BASIC the MITS Altair 8800 runs — the 1975–76 interpreter that every later Microsoft BASIC descends from.

In this reference: Hardware · Escape codes · File formats · Argument notation

Notes and caveats ​

  • ? stands for PRINT, and is shown beside it in the table below; the search box finds the keyword by it.
  • Multiple statements per line are allowed with :, and ? is shorthand for PRINT. There is no ' shorthand for REM.
  • ^ is the power operator — there is no up-arrow spelling — and it folds left to right, so 2^3^2 is 64. AND, OR and NOT combine their operands bit by bit, and a true comparison is -1. There is no integer-division, remainder or exclusive-OR operator: use INT(a/b) and a-b*INT(a/b).
  • Only the first two characters of a variable name are significant, so COUNT and COST are the same variable. $ is the only type suffix — %, ! and # are later additions, and X%=1 is stored happily and then fails when it runs.
  • Spaces are ignored outside strings, REM and DATA, so FORI=1TO10 is valid. The other side of that rule is that a keyword is recognised inside a name: a variable called TOTAL contains TO and mis-runs without reporting an error.
  • String space is 50 bytes until a program says CLEAR n. Assigning a literal (A$="*") costs nothing; concatenating does.
  • PEEK, POKE, INP, OUT and WAIT all take decimal addresses. There is no hexadecimal notation anywhere in this BASIC.

Command Function Operator

Syntax & description
-<number> - <number> | -<number>
Subtracts, or negates.
*<number> * <number>
Multiplies.
/<number> / <number>
Divides. Dividing by zero gives ?/0 ERROR.
^<number> ^ <number>
Raises to a power, computed through EXP and LOG. This is the only power operator - there is no up-arrow spelling.
+<number> + <number> | <string> + <string>
Adds two numbers, or joins two strings.
<<number> < <number>
Less than. Combines with = and > to make <= and <>.
<=<number> <= <number> | <string> <= <string>
Less than or equal.
<><number> <> <number> | <string> <> <string>
Not equal.
=<var> = <expr> | <number> = <number>
Assignment in a statement, equality in an expression. True is -1 and false is 0.
><number> > <number>
Greater than. Combines with = and < to make >= and <>, which are stored as two tokens.
>=<number> >= <number> | <string> >= <string>
Greater than or equal.
ABSABS(<number>)
The argument without its sign.
AND<number> AND <number>
Bitwise AND of two 16-bit integers. Comparisons yield -1 or 0, so it doubles as the logical AND - but both sides are always evaluated.
ASCASC(<string>)
The ASCII code of the first character. An empty string gives ?FC ERROR.
ATNATN(<number>)
Arctangent, in radians.
CHR$CHR$(<number>)
The one-character string for an ASCII code, 0-255.
CLEARCLEAR [<number>]
Sets every variable to zero and discards arrays. With an argument it also sets the number of bytes reserved for strings, which is 50 until a program says otherwise.
CLOADCLOAD <filename>
Loads a program from cassette through the 88-ACR board, matching the one-character name.
CONTCONT
Resumes a program stopped by STOP or CTRL-C, from where it stopped. Editing any line makes it impossible.
COSCOS(<number>)
Cosine of an angle in radians. Present only when the cold-start dialogue was answered Y to WANT SIN-COS-TAN-ATN, which is how this IDE starts the machine.
CSAVECSAVE <filename>
Saves the program to cassette through the 88-ACR board under a one-character name.
DATADATA <constant>[, <constant>]…
Inline constants for READ to consume in program order. Strings may be quoted; the rest of the statement is stored exactly as typed.
DEFDEF FN<letter>(<numvar>) = <expr>
Defines a single-expression numeric function. The name is FN plus one letter, and the definition must be executed before the function is called.
DIMDIM <var>(<number>[, <number>]…)
Declares an array and its bounds. Subscripts start at 0, so DIM A(10) has eleven elements; an undeclared array is created with bound 10 on first use.
ENDEND
Stops the program and returns to the OK prompt without printing a BREAK message; unlike STOP, execution cannot then be resumed with CONT.
EXPEXP(<number>)
e raised to the power of the argument.
FNFN<letter>(<number>)
Calls a function defined by DEF.
FORFOR <numvar> = <number> TO <number> [STEP <number>]
Opens a counting loop that runs up to the matching NEXT. STEP sets the increment (default 1, may be negative or fractional); the body always runs at least once.
FREFRE(<number>)
The number of bytes left for the program and its variables. The argument is ignored.
GOSUBGOSUB <line>
Calls a subroutine, remembering where to come back to. RETURN comes back.
GOTOGOTO <line>
Jumps to a line number. Written GO TO with a space as well, which crunches to the same token.
IFIF <expr> THEN <line> | <statement>
Runs the rest of the line when the expression is non-zero. There is no ELSE in 8K BASIC: write a second IF, or jump.
INPINP(<port>)
Reads a byte from an 8080 I/O port (0-255). Polling the console ports for a keystroke does not work: BASIC checks them for CTRL-C between statements and takes the character first.
INPUTINPUT [<prompt>;] <var>[, <var>]…
Prints the prompt (or ? when there is none) and waits for a whole line to be typed at the terminal. This is the machine's only key read - 8K BASIC has no INKEY$ - so an interactive program takes one turn per typed line.
INTINT(<number>)
The largest whole number not greater than the argument, so INT(-1.5) is -2.
LEFT$LEFT$(<string>, <length>)
The leftmost n characters.
LENLEN(<string>)
The number of characters in a string.
LET[LET] <var> = <expr>
Assigns a value. The keyword is optional and almost always left out; it costs a byte of program text and nothing else.
LISTLIST [<line>]
Lists the program to the terminal, from the given line onwards where one is named. CTRL-C stops a listing.
LOGLOG(<number>)
Natural logarithm. Zero or a negative argument gives ?FC ERROR.
MID$MID$(<string>, <start>[, <length>])
The substring starting at position n (counted from 1), of the given length or to the end. It is a function only - unlike later Microsoft BASICs it cannot be assigned to.
NEWNEW
Erases the program and all variables.
NEXTNEXT [<numvar>[, <numvar>]…]
Closes the innermost FOR loop and jumps back to it. Naming the variable closes that loop specifically, and several may be closed in one statement.
NOTNOT <number>
Bitwise complement of the 16-bit integer value, so NOT 0 is -1 and NOT -1 is 0.
NULLNULL <number>
Sets how many null characters are sent after each line - the delay a printing terminal needed for its carriage to return. 0 for a glass terminal.
ONON <expr> GOTO | GOSUB <line>[, <line>]…
Computed jump: the expression picks the first, second, third… line in the list. A value of 0 or one past the end falls through to the next statement.
OR<number> OR <number>
Bitwise OR of two 16-bit integers, and so also the logical OR.
OUTOUT <port>, <byte>
Writes a byte to an 8080 I/O port (0-255). The console is the 88-2SIO at ports 16 and 17; writing to those interferes with BASIC's own terminal.
PEEKPEEK(<addr>)
The byte at a decimal address. The whole 64K is readable, including the interpreter itself.
POKEPOKE <addr>, <byte>
Writes a byte to a decimal address. BASIC itself lives in RAM here, from address 0 up, so a wrong address can corrupt the interpreter.
POSPOS(<number>)
The current print column, counted from 0. The argument is ignored.
PRINT?PRINT [<expr>][;|,]…
Prints to the terminal. A comma moves to the next 14-column zone, a semicolon stays put, and a trailing separator suppresses the newline. ? is shorthand for it.
READREAD <var>[, <var>]…
Takes the next constant from the DATA statements, in program order. RESTORE winds the pointer back to the first.
REMREM <comment>
A comment. Everything after it to the end of the line is stored verbatim and never executed - including a colon, so no statement can follow one.
RESTORERESTORE
Winds the READ pointer back to the first DATA statement in the program.
RETURNRETURN
Returns to the statement after the GOSUB that called this subroutine.
RIGHT$RIGHT$(<string>, <length>)
The rightmost n characters.
RNDRND(<number>)
A random number between 0 and 1. A positive argument gives the next in the sequence, 0 repeats the last one, and a negative argument reseeds.
RUNRUN [<line>]
Clears the variables and starts the program, from the given line where one is named.
SGNSGN(<number>)
The sign of the argument: -1, 0 or 1.
SINSIN(<number>)
Sine of an angle in radians.
SPC(SPC(<number>)
Prints that many spaces. Only valid inside PRINT; unlike TAB( it is relative to where the print position already is.
SQRSQR(<number>)
Square root. A negative argument gives ?FC ERROR.
STEPSTEP <number>
The increment of a FOR loop. Negative counts down; fractional steps are allowed.
STOPSTOP
Halts with BREAK IN <line>. Unlike END the program can be resumed from that point with CONT.
STR$STR$(<number>)
The string PRINT would produce for a number, leading space and all.
TAB(TAB(<number>)
Moves the print position to that column, counted from 0. Only valid inside PRINT, and it can only move forwards.
TANTAN(<number>)
Tangent of an angle in radians.
THENTHEN <line> | <statement>
Introduces what an IF does when its condition holds. A bare line number means GOTO.
TOTO
The upper limit of a FOR loop, and the second half of GO TO.
USRUSR(<addr>)
Calls the machine-code routine whose address is held in the USR vector, passing the argument and returning its result.
VALVAL(<string>)
The number at the front of a string, or 0 where there is none.
WAITWAIT <port>, <mask>[, <mask>]
Spins until an input port, exclusive-ORed with the third argument and masked with the second, is non-zero. Nothing but a reset breaks the wait if the condition never comes true.
Argument notation

Anything in <angle brackets> is a value you supply; everything else is typed exactly as shown. [square brackets] mark an optional part, | separates alternatives, and … means the part before it can repeat. The arguments on this page are:

<number>
a numeric expression
<string>
a string expression
<expr>
a value of either type, where the keyword takes both
<byte>
a value from 0 to 255
<constant>
a literal number or string, not an expression
<var>
a variable of either type
<numvar>
a numeric variable
<letter>
a single letter
<line>
a line number
<statement>
one BASIC statement
<comment>
free text, to the end of the line
<start>
the position something starts at, counting from 1
<length>
how many characters
<prompt>
text shown before the input; a literal, not an expression
<filename>
the name of a file on tape or disc
<addr>
a memory address
<port>
an input/output port, by number
<mask>
a bit mask, one bit per item

Showing 73 of 73 keywords

The interpreter ​

The Altair had no firmware. BASIC arrived on a paper tape you loaded into RAM at address 0 before anything else could happen, so what the IDE calls this machine's ROM is really that tape: Altair 8K BASIC 4.0, 8 KB of it, copied to address 0 at reset. It runs from RAM, which is why a wrong POKE can corrupt the interpreter itself.

The image is bundled, and starts automatically — the cold-start dialogue (MEMORY SIZE?, TERMINAL WIDTH?, WANT SIN-COS-TAN-ATN?) is answered for you with 48 KB, 72 columns and the transcendental functions kept. You can install a different Altair BASIC in the settings page; the addresses in this reference were read off the 4.0 eight-K tape and are not promised of another.

Released under GNU GPL v3.0. Some ROM images are third-party copyrighted works, separate to this project, strictly for personal/educational purposes.