Microsoft's 6502 BASIC
Bill Gates and Ric Weiland completed Microsoft's BASIC for the 6502 in 1976. This is its version 1.1, of 1978, from the source Microsoft released under the MIT licence in 2025: your browser assembles that source and runs it on a 6502, as five of the machines it was built for.
How it works
This is Microsoft's own BASIC: the 1978 source, exactly as Microsoft released it (m6502.asm, under the MIT licence). It was written in DEC's MACRO-10, on a PDP-10 mainframe, and the source still builds for "PDP-10 SIMULATING 6502", as Microsoft ran it before any 6502 was at hand: try the PDP-10 above, and its DDT. When you open this page, your browser assembles that source into about 8K of 6502 machine code and runs it on Moonbase's own 6502, simulated in your browser, drawn beside the screen and lit by every instruction. The keys, the screens in Moonbase's own characters, and SAVE and LOAD come from this site, standing in for each machine's own ROM. And hidden in the code are its authors' signatures: type WAIT 6502,1 on the PET, or A at MEMORY SIZE? on the Apple.
TITLE BASIC M6502 8K VER 1.1 BY MICRO-SOFTSEARCH M6502SALLRADIX 10 ;THROUGHOUT ALL BUT MATH-PAK. $Z:: ;STARTING POINT FOR M6502 SIMULATOR ORG 0 ;START OFF AT LOCATION ZERO.SUBTTL SWITCHES,MACROS. REALIO=4 ;5=STM ;4=APPLE. ;3=COMMODORE. ;2=OSI ;1=MOS TECH,KIM ;0=PDP-10 SIMULATING 6502…How BASIC keeps a program
When you type a line with a number in front and press Return, BASIC keeps it in memory as bytes. Each keyword, such as PRINT or GOTO, becomes a single byte, a token, so the program takes less room and runs quicker. Everything else is kept as you typed it, a byte for each character.
Each line starts with two bytes that point to where the next line starts, then two bytes for its line number, and ends with a 0. Two bytes make one number with the low byte first: $0F $04 is $040F. To find a line, for a GOTO, BASIC follows these from the first line until it reaches the number. A pointer of 0 ends the program. LIST turns the tokens back into words as it prints them, and SAVE writes these same bytes, so a saved program is smaller than the text you typed. (Numbers starting with $ are in hex: see Bits and bytes.)
Type a line or two, and see the bytes Commodore's build keeps:
Its functions
BASIC's functions, in the order of its table of their addresses (and FN, those a program makes for itself with DEF FN). The arithmetic is Microsoft's own, in 6502: add, subtract, multiply and divide, and the rest made of those, on numbers of five bytes. One flag, KIMROM, set only for a KIM-1 with BASIC in its ROM, leaves COS, SIN, TAN and ATN out.
- SGN(X)
- −1, 0 or 1, by X's sign
- INT(X)
- the whole number at or below X
- ABS(X)
- X without its sign
- USR(X)
- a routine of the program's own, in machine code, at the address it has set, X handed to it
- FRE(X)
- the bytes free between the variables and the strings, the strings tidied up first; X is not used (FRE(0)), and more than 32,767 shows as negative
- POS(X)
- the column the next character will print in; X is not used
- SQR(X)
- the square root: X to the power ½, by LOG and EXP
- RND(X)
- a random number between 0 and 1: for X above 0, the next, made from the last by multiplying by one constant, adding another and swapping its bytes about; for X of 0, Commodore's build reads its timers and the others give the last again; for X below 0, a new sequence, started from X
- LOG(X)
- the natural logarithm: X split into a power of 2 and a fraction, a polynomial on the fraction, times LN(2)
- EXP(X)
- e to the X: as 2 to a power, the whole part straight into the exponent, a polynomial for the fraction
- COS(X)
- SIN(X + π/2)
- SIN(X)
- X divided by 2π, its fraction folded into a quarter turn, then a polynomial of six constants
- TAN(X)
- SIN(X) divided by COS(X)
- ATN(X)
- the angle whose tangent is X: made positive and less than 1, then a polynomial
- PEEK(X)
- the byte in memory at address X
- LEN(X$)
- the length of a string
- STR$(X)
- a number as a string, as PRINT would print it
- VAL(X$)
- a string read as a number
- ASC(X$)
- the code of a string's first character
- CHR$(X)
- the character with the code X
- LEFT$(X$,N)
- a string's first N characters
- RIGHT$(X$,N)
- its last N characters
- MID$(X$,S,N)
- N characters from the Sth; without N, the rest from the Sth
Each number is five bytes. The first is its exponent, the power of two with 128 added, 0 for the number 0; the other four are its mantissa, its digits in binary, the first bit kept for its sign. The fifth byte is the source's ADDPRC, "additional precision": with it BASIC keeps about nine digits, without it six.