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 forPRINT, 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 forPRINT. There is no'shorthand forREM. ^is the power operator — there is no up-arrow spelling — and it folds left to right, so2^3^2is64.AND,ORandNOTcombine their operands bit by bit, and a true comparison is-1. There is no integer-division, remainder or exclusive-OR operator: useINT(a/b)anda-b*INT(a/b).- Only the first two characters of a variable name are significant, so
COUNTandCOSTare the same variable.$is the only type suffix —%,!and#are later additions, andX%=1is stored happily and then fails when it runs. - Spaces are ignored outside strings,
REMandDATA, soFORI=1TO10is valid. The other side of that rule is that a keyword is recognised inside a name: a variable calledTOTALcontainsTOand 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,OUTandWAITall 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. |
ABS | ABS(<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. |
ASC | ASC(<string>)The ASCII code of the first character. An empty string gives ?FC ERROR. |
ATN | ATN(<number>)Arctangent, in radians. |
CHR$ | CHR$(<number>)The one-character string for an ASCII code, 0-255. |
CLEAR | CLEAR [<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. |
CLOAD | CLOAD <filename>Loads a program from cassette through the 88-ACR board, matching the one-character name. |
CONT | CONTResumes a program stopped by STOP or CTRL-C, from where it stopped. Editing any line makes it impossible. |
COS | COS(<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. |
CSAVE | CSAVE <filename>Saves the program to cassette through the 88-ACR board under a one-character name. |
DATA | DATA <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. |
DEF | DEF 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. |
DIM | DIM <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. |
END | ENDStops the program and returns to the OK prompt without printing a BREAK message; unlike STOP, execution cannot then be resumed with CONT. |
EXP | EXP(<number>)e raised to the power of the argument. |
FN | FN<letter>(<number>)Calls a function defined by DEF. |
FOR | FOR <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. |
FRE | FRE(<number>)The number of bytes left for the program and its variables. The argument is ignored. |
GOSUB | GOSUB <line>Calls a subroutine, remembering where to come back to. RETURN comes back. |
GOTO | GOTO <line>Jumps to a line number. Written GO TO with a space as well, which crunches to the same token. |
IF | IF <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. |
INP | INP(<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. |
INPUT | INPUT [<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. |
INT | INT(<number>)The largest whole number not greater than the argument, so INT(-1.5) is -2. |
LEFT$ | LEFT$(<string>, <length>)The leftmost n characters. |
LEN | LEN(<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. |
LIST | LIST [<line>]Lists the program to the terminal, from the given line onwards where one is named. CTRL-C stops a listing. |
LOG | LOG(<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. |
NEW | NEWErases the program and all variables. |
NEXT | NEXT [<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. |
NOT | NOT <number>Bitwise complement of the 16-bit integer value, so NOT 0 is -1 and NOT -1 is 0. |
NULL | NULL <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. |
ON | ON <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. |
OUT | OUT <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. |
PEEK | PEEK(<addr>)The byte at a decimal address. The whole 64K is readable, including the interpreter itself. |
POKE | POKE <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. |
POS | POS(<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. |
READ | READ <var>[, <var>]…Takes the next constant from the DATA statements, in program order. RESTORE winds the pointer back to the first. |
REM | REM <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. |
RESTORE | RESTOREWinds the READ pointer back to the first DATA statement in the program. |
RETURN | RETURNReturns to the statement after the GOSUB that called this subroutine. |
RIGHT$ | RIGHT$(<string>, <length>)The rightmost n characters. |
RND | RND(<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. |
RUN | RUN [<line>]Clears the variables and starts the program, from the given line where one is named. |
SGN | SGN(<number>)The sign of the argument: -1, 0 or 1. |
SIN | SIN(<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. |
SQR | SQR(<number>)Square root. A negative argument gives ?FC ERROR. |
STEP | STEP <number>The increment of a FOR loop. Negative counts down; fractional steps are allowed. |
STOP | STOPHalts 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. |
TAN | TAN(<number>)Tangent of an angle in radians. |
THEN | THEN <line> | <statement>Introduces what an IF does when its condition holds. A bare line number means GOTO. |
TO | TOThe upper limit of a FOR loop, and the second half of GO TO. |
USR | USR(<addr>)Calls the machine-code routine whose address is held in the USR vector, passing the argument and returning its result. |
VAL | VAL(<string>)The number at the front of a string, or 0 where there is none. |
WAIT | WAIT <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.