# Yes, Microsoft 6502 BASIC was clearly a port of their 8080 BASIC. Unfortunately the original 8080 source code for Microsoft BASIC [isn't easily available][11838], so we can't compare it directly to that without going to the Harvard University library to read the paper copy. But the Microsoft source code for a later version of their 8080 BASIC, BASIC-80 5.2 (actually marked 5.11 in the source) is [available online][5.2]. This is copyright 1982 (from the copyright notice in `INIT.MAC`), but contains material obviously from the original 8080 source code, such as the following comment in `BINTRP.MAC`: ;--------- ---- -- ---- ----- --- ---- ----- ;COPYRIGHT 1975 BY BILL GATES AND PAUL ALLEN ;--------- ---- -- ---- ----- --- ---- ----- ; ;ORIGINALLY WRITTEN ON THE PDP-10 FROM ;FEBRUARY 9 TO APRIL 9 1975 Comparing this with the [6502 source code][6502] we see substantial similarities in the overall organization of the code and almost exact correspondence of many routines within it. ### START and INIT For example, the entry point in both versions is at address 0 and contains `JMP INIT`; in both cases the `INIT` routine overwrites the target of this `JMP` with the address of a routine called `READY` that does a "warm start". After that there are a couple of words storing the addresses of routines to convert a floating point number to an integer and vice versa. Here's the 8080 version from 1982: PUBLIC START START: PUBLIC JMPINI JMPINI: JMP INIT ;INIT IS THE INTIALIZATION ROUTINE ;IT SETS UP CERTAIN ;LOCATIONS DELETES FUNCTIONS IF ;DESIRED AND ;CHANGES THIS TO JMP READY ;WARM START FOR ISIS ;OF THE ROUTINE TO CONVERT [A,B] ;TO A FLOATING POINT NUMBER IN THE FAC DW FRCINT ;TURN FAC INTO AN INTEGER IN [H,L] DW MAKINT ;TURN [H,L] INTO A VALUE IN THE FAC ;SET VALTYP FOR INTEGER And the 6502 version from 1978: START: JMP INIT ;INITIALIZE - SETUP CERTAIN LOCATIONS ;AND DELETE FUNCTIONS IF NOT NEEDED, ;AND CHANGE THIS TO "JMP READY" ;IN CASE USER RESTARTS AT LOC ZERO. RDYJSR: JMP INIT ;CHANGED TO "JMP STROUT" BY "INIT" ;TO HANDLE ERRORS. ADRAYI: ADR(AYINT) ;STORE HERE THE ADDR OF THE ;ROUTINE TO TURN THE FAC INTO A ;TWO BYTE SIGNED INTEGER IN [Y,A] ADRGAY: ADR(GIVAYF)> ;STORE HERE THE ADDR OF THE ;ROUTINE TO CONVERT [Y,A] TO A FLOATING ;POINT NUMBER IN THE FAC. ### STROUT Another example is the `STROUT` routine, which clearly works in the same way, modulo the differences in processor architecture, and even has some comments that are nearly identical. Here's the 8080 version: ; ; PRINT THE STRING POINTED TO BY [H,L] WHICH ENDS WITH A ZERO ; IF THE STRING IS BELOW DSCTMP IT WILL BE COPIED INTO STRING SPACE ; STROUI: INX H ;POINT AT NEXT CHARACTER STROUT: CALL STRLIT ;GET A STRING LITERAL ; ; PRINT THE STRING WHOSE DESCRIPTOR IS POINTED TO BY FACLO. ; STRPRT: CALL FREFAC ;RETURN TEMP POINTER BY FACLO CALL GETBCD ;[D]=LENGTH [B,C]=POINTER AT DATA INR D ;INCREMENT AND DECREMENT EARLY ;TO CHECK FOR NULL STRING STRPR2: DCR D ;DECREMENT THE LENGTH RZ ;ALL DONE LDAX B ;GET CHARACTER TO PRINT CALL OUTDO CPI 13 CZ CRFIN INX B ;POINT TO THE NEXT CHARACTER JMP STRPR2 ;AND PRINT IT... PAGE And here's the 6502 version: ; ; PRINT THE STRING POINTED TO BY [Y,A] WHICH ENDS WITH A ZERO. ; IF THE STRING IS BELOW DSCTMP IT WILL BE COPIED INTO STRING SPACE. ; STROUT: JSR STRLIT ;GET A STRING LITERAL. ; ; PRINT THE STRING WHOSE DESCRIPTOR IS POINTED TO BY FACMO. ; STRPRT: JSR FREFAC ;RETURN TEMP POINTER. TAX ;PUT COUNT INTO COUNTER. LDYI 0 INX ;MOVE ONE AHEAD. STRPR2: DEX BEQ PRTRTS ;ALL DONE. LDADY INDEX ;PNTR TO ACT STRNG SET BY FREFAC. JSR OUTDO INY CMPI 13 BNE STRPR2 JSR CRFIN ;TYPE REST OF CARRIAGE RETURN. JMP STRPR2 ;AND ON AND ON. ### PTRGET Even routines that are different due to feature changes are pretty clearly derived from common original source. For example, the `PTRGET` routine that that reads a variable name and fetches its value uses a pair of zero-page memory locations in the 6502 version to store the variable name, which is limited to two characters in that older version of BASIC. The newer 8080 code allows up to 40 characters in a variable name, but still stores the first two characters of the name in the C and B registers (memory was used in the 6502 because it has far fewer registers) and compares those first, only moving on to a further comparison with the rest of the name in a memory buffer if that fails. And of course there's the similarity in the comments and routine name itself. The 8080 version: ; ROUTINE TO READ THE VARIABLE NAME AT THE CURRENT TEXT POSITION ; AND PUT A POINTER TO ITS VALUE IN [D,E]. [H,L] IS UPDATED ; TO POINT TO THE CHARACTER AFTER THE VARIABLE NAME. ; VALTYP IS SETUP. NOTE THAT EVALUATING SUBSCRIPTS IN ; A VARIABLE NAME CAN CAUSE RECURSIVE CALLS TO PTRGET SO AT ; THAT POINT ALL VALUES MUST BE STORED ON THE STACK. ; ON RETURN, [A] DOES NOT REFLECT THE VALUE OF THE TERMINATING CHARACTER ; PTRGET: XRA A ;MAKE [A]=0 And the 6502 version: ; ROUTINE TO READ THE VARIABLE NAME AT THE CURRENT TEXT POSITION ; AND PUT A POINTER TO ITS VALUE IN VARPNT. [TXTPTR] ; POINTS TO THE TERMINATING CHARCTER.. NOT THAT EVALUATING SUBSCRIPTS ; IN A VARIABLE NAME CAN CAUSE RECURSIVE CALLS TO "PTRGET" SO AT ; THAT POINT ALL VALUES MUST BE STORED ON THE STACK. ; PTRGET: LDXI 0 ;MAKE [ACCX]=0. ### Comparison with Other Object Code Though we don't have original source for an 8080 version of Microsoft BASIC from the same era as the 6502 source, we do have binaries that can be disassembled. Comparing [this disassembly of Altair BASIC 3.2][altair] we can also find substantial similarities in the code (including all the routines mentioned above), though of course there are no comments to compare. I myself have been working on a [disassembly of the 6800 BASIC][6800] that Microsoft wrote for the Altair 680B after they'd written the 8080 basic for Altair's 8800 but probably before they started the 6502 version. Both ports were done by Ric Weiland, and again the 6800 version shows the same substantial similarities in code organization and the details of how the particular routines work. [11838]: https://retrocomputing.stackexchange.com/q/11838/7208 [5.2]: https://winworldpc.com/download/c2bfc380-c2b2-c2b4-7d00-11c3a7c29d25 [6502]: https://www.pagetable.com/docs/M6502.MAC.txt [altair]: http://altairbasic.org/ [6800]: https://github.com/0cjs/altair-680-basic