You can now download a PDF of my lecture from VCF East 9.1.
If you're so inclined, here is a listing of my class notes that go along with the PDF link above. Not all slides have notes/I didn't need them.
SLIDE 3: Original scope of the program, has evolved over time to include more hardware interaction. Timesharing BASIC was not designed for hardware interaction.
SLIDE 4: This class is intended for those who have been introduced to the BASIC language and want to go further with the language in the “vintage computer” perspective. It is also intended for those who have already learned another older language and need only a brief introduction to what is for them a second or third programming language.
SLIDE 6: Constants. BASIC programs are made up of statements that contain keywords, variables, operators, and constants. Most computers can have two kinds of constants.
1. Numeric constants are numbers with or without a decimal point. If a number has a decimal point it is called a floating point number. A number without a decimal point is often called an integer. Floating point is used to represent a wider range of numbers than integer (see Section VI on data representation for more details).
An integer constant, like 5, is represented as 5.0.
2. The other kind of constant is a character string. A character string constant is signalled by a quote (")
mark. The symbols "AB" mean the string of two characters, A followed by B. 2.
2. Variables. Variables are "names" that may take on different values during a problem. In BASIC the first character in a variable must be alphabetic and not numeric. A= 2 causes the computer to set A = 2.
SLIDE 10: Dartmouth BASIC had statements for matrix and array manipulation already in its third edition (1966)
DIM statement creates the array space in memory.
MAT READ Enters data into numeric and string arrays, several arrays can be read at the same time using the same MAT READ statement by separating the array names with commas
SLIDE 11: DEC and subsequent versions of BASIC did away with MAT READ and other MATrix operations.
NOTE: DIM (COLUMNS,ROWS)
While we’re at it, DIGITAL BASIC differs from Dartmouth in very few ways. Most notably related to function and not syntax
Use of BASIC statements in immediate mode
Use of all BASIC commands in deferred mode (line number of a program)
- recursive subroutines
- Multiple statement lines
We don’t have character string manipulation yet.
NO TAB printing (but you could simulate with a function using ascii character 32 5 times to make 5 spaces.
All array variables must be declared in a DIM statement before use
SLIDE 13: This exercise can be done in Dartmouth BASIC and most other BASICs using matricies and a bit of randomization.
First select moves randomly until the knight reaches a dead end due to the fact that all reachable squares have already been visited.
Use an 8-by-8 array called B to simulate the board.
Initialize all entries are zero to indicate open positions.
Place the move numbers in the squares as the knight moves about the board.
The 8-by-2 array U stores all eight possible moves from the present position.
The eight moves are scanned for legal use in lines 220, 230, and 240 of program
INT ((R1-1)/8) = 0 in line 220 is equivalent to (0If the move is legal, it’s added to the T array. When all legal moves are in the T array, K1 is the legal number of moves
If K1 is zero, then the knight has reached a dead end.
SLIDE 15: See vintagecomputer.net for the full articles.
June and October 1977 Kilobaud BASIC Speed Comparison Articles
For the computer person needs ways of measuring the capacity of the computer hardware and software
There were four microcomputer chips represented in the benchmarks. Apple (not Zapple) uses a 6502. Southwest Tech, the Altair 680b, and the Sphere use the 6800. The TDL ZPU and the Digital Group Z-80 use the Z-80. All others use the 8080.
By comparing the amount of time it takes each system to run them, you can make a pretty good estimate of how much faster one system is over another for the kind of work you tested.
If after running a benchmark program on system X 23 percent faster than system Y that doesn't mean that system X is 23 percent faster for everything.
statistical calculation programs differ from text-processing programs / "number crunching" (square roots, trig functions, etc.) but terrible at string manipulation.
If you have the fastest and most flexible CPU in the world, but you're running a badly written BASIC on it, it's not going to measure up too well. The same is true of a beautifully written BASIC on a poorly designed CPU.
SLIDE 18: These are the bechnmark tests
The first benchmark is nothing but a simple FORNEXT loop. All it does is make the variable K go from one to a thousand.
The second benchmark program does the same thing (logically), but in a different way. Instead of using a FORNEXT loop, we set K equal to zero, add one to it, and check to see if we've reached 1000 yet. If not. we go back and add one again.
The third benchmark adds statement 510 to the program. It does a divide, a multiply, an add, and a subtract - using variables only.
The fourth benchmark program replaces statement 510 with one that does the same operations as the third, but uses one-digit constants instead. (based on how BASIC written most times this is longer than 3rd benchmark)
Benchmark number 5 adds statements 520 and 820. All they accomplish are a simple GOSUB to a dummy subroutine that does nothing but RETURN
The sixth benchmark has some interesting aspects, but it's mostly a preparation for the next one. It adds statements 430, 530 and 540. It creates the array M and does a five-time FOR-NEXT loop for each of the thousand times in outer loop. This tests a different condition than the first benchmark, which is also a FOR-NEXT loop, because this one executes a small inner loop a thousand different times. Initializing a small loop one thousand times is quite a bit different from initializing a large loop once (as Benchmark 1 did).
7 adds statement 535. This tests the amount of time it takes to place a value in an array. Since arrays are so frequently used by so
many programs, it's important to know how long it takes BASIC to figure out which element you're referring to (the "L-th" one here)
and then put a value into it (A). Notice that we're executing this statement 5000 times.
Looking at the times for benchmark 7 as our overall measurement.
SLIDE 19: TDL's Zapple BASIC was run on an Altair 8800a with a TDL ZPU board in it. According to the article neither the ZPU nor the Cromemco Z80 board will not work in an 8800b
“First, we tested more versions of Altair BASIC than anything else. The reason for this is pretty simple. More people used it than any other BASIC we ran into, and more versions of it exist than any other.”
IMSAI BASIC is incompatible with all but benchmark 1 and could not run. Specifically, any kind of branch instruction (GOTO, GOSUB, etc.) wouldn't work! Benchmark 3 had to be done with a FOR-NEXT loop (like benchmark 1), as did all subsequent benchmarks. Benchmarks 6 and 7 didn't have the GOSUB-RETURN statements. Runs on a ePROM using a teletype. Not really a fair test.
“We made sure that no slow memory was used. All machines were thought to be running at their full rated speeds by their owners. “
For kicks also tested BASIC on a multi-millon dollar Control Data Cyber 174 …Apple INTEGER BASIC only took 27 times as long as the CDC. Will return to this subject with Bill Gates’ comments below
SLIDE 21: Comments from Robert Uiterwyk, the man who developed SWTP's 8K BASIC
Presenter note: PET 6502 BASIC has 10 significant digits and still fast, so CPU has something to do with speed.
Slide 22: "Regarding the clock frequency of OSI-shipped Challengers. Their engineer, Eric Davis, informed me that all OSI Challengers are shipped running at only 1 MHz. All OSI Challengers shipped since some time last year have CPUs and memory all guaranteed to run at 2 MHz. The reason Challengers leave OSI at 1 MHz is because 'they run the disk system currently with the clock at 1 MHz.' My
system is not a disk system, and even disk systems could be run at 2 MHz for running programs (that don't use the disk)."
It turns out that there's !I potentiometer (near the ROM, we're told) that can be adjusted to "soup up" the Challenger.
SLIDE 25: Note the PET is a prototype. More on OSI version of Micro-Soft BASIC later in the presentation.
“If we look at the list with the intent of determining which microprocessor chip is the fastest, we have to agree with Bill Gates at this point and give the nod to the 6502. It's hard to tell how much of its superior performance is due to superior software, but there's no question that it came out on top in our tests.” …”The Z-80 isn't far behind, but has to be run at 4 MHz to make a really good showing.”
“…The 8080 is next, but we found a huge range of fast and slow 8080 BASICs. The 6800 doesn't look so good, but certainly seems to have a lot of unrealized potential.
SLIDE 35: mem location 769 is the first location that displayed. The first line of the program is:
16 3 10 0 66 171 48 58 65 36 171 34 0
The first two bytes, 16 3, is the location of the next line of the program. The next two bytes are the number of the current line (10 0) and the end of the line is marked by a 0. (0's are often used as markers in MICROSOFT as they occur infrequently in text storage.)
All of the commands, what MICROSOFT calls "reserved words", are encoded in MICROSOFT codes. The arithemitic operators ( , - , * , / , "and" ) are also considered commands and encoded. The 171's appearing in the line are " " statements. (See list of the MICROSOFT codes below.)
MICROSOFT uses ASCII to store print statements, remarks, variable names, and, all numbers that appear in the text. All line numbers in GOTO statements, all arithmetic values, all variable values, and all values in IF statements are stored in ASCII. Miscellaneous characters such as brackets and " marks are normally stored in ASCII.
The only thing that does not seem to have a hard and fast rule are REM and DATA statements. Those two commands may be found either in ASCII or code and seem to work as well either way. There does not appear to be any discernible pattern to the choice of method of storage. Note that REM and DATA were “advanced BASIC” from the original Dartmouth BASIC.
The ASCII representation of numbers is significant. It explains why statements using variable names normally execute faster than statements using the numerical values for the operation. BASIC has to convert the ASCII numbers to BCD for storage and to HEX or arithemetic operations before the can be used. Variable values are already processed and ready in a table and can be looked up faster than they can be converted.
One significant fact shows that more than one person worked on MICROSOFT who did not tell the other guy what he was doing. The convention for storing a string function varies. Names of string variables store the $ after the name and some string functions store the $ in the text. Other string functions such as MID$ store only on the one byte command (?) and assume the presence of the first. Look for it either way in the text if you are looking for a string variable. Brackets show the same inconsistency. Some functions which require operators store both brackets, but other store only the second bracket, ")" and assume the presence of the first. That doesn't mean that you can leave them out when you type in the text, just that you can't find them if you look at the stored code.
That actually ends the line of MICROSOFT, but while we are at it, we might as well look at the stuff that follows. The first thing is the variable tables. The variables are stored in the order that they are found in the text. (For fast access, initialize he most used variable first.) Each variable takes six bytes. Regular variables start with two bytes for the name (even if it is a one byte name), followed by three bytes of packed BCD giving the six digit value and ending with a 0 which marks the end of the table entry.
String variables are stored - sort of - in the same table. Their entries are also six bytes long. The differences start in the second ASCII character of the string name plus 128 to show that it is a string entry. The next bytes store the address of the last place that it appeared in the text. The end is marked by 0.
If you look at the sample program, you will notice that the first thing following the 0 that ends the program is 66 0. The ASCII representation of he variable name "B". If it were a two letter name, the second bytes would contain the second character of the name. The next three bytes contain the six digit value of "B" in packed BCD, which is a bear to read. The last zero marks the end of the table entry.
The next entry (65 128 1 13 3 0) contains the information on A$. The two byte name is coded with ASCII for the letter and the ASCII plus 128 for the next letter to show that it is a string. The next byte is the length of htee string and the next two bytes (13 3) are the
memory location where the first text reference is found. The 0 marks the end of the table. The last entry in the table is for variable X which shows the current value of 831 (88 0 138 78 128 0) .
If there were subscripted variables, they would follow the regular variable table (to look at a subscripted variable table, change line 10 to 10 A(1)=1:A(2)=31 and change 830 in line 20 to 900. The tablee begins with a variable name, the length of the table and then the actual entries. The system marks off four spaces for each entry - one for the marker number and three for the six digits of the variable value. It sets aside enough space for ten entries and fills them with zeros if you don't use them - so it pays to dimention down if you are using less than eight values on a subscripted variable. MICROSOFT will still stubbornly dimension off more than you need, but you will be closer. Dimentioned string variables appear in a similar fashion in the table, but pointers to their position in text are given rather than the actual values.
Now get to work on those text editors and renumbers that you have been thinking about!
SLIDE 39: Let's start with a simple move from left to right.
Line 100 sets three values
number of a screen location on the left edge about a third of the way down the screen - S=53603
screen width W = 32
ASCII code for the character we want to display – make an “airplane” together use DI = 237 and D2 = 234
also use C as a counter, set to 0
Line 50 blanks the screen by printing blanks
Line 110 increments the counter to position the target and easily reset the end of the line
120 shows the actual target to the display, and blanks the space the counter was at before it was incremented, and then places the target the next space over.
IM = starting point for missle 53805 which is down at the bottom of the screen, middle-ish.
Noticed an error, MD should be 190 (slash char) not 65 (?)
Line 90 used to establish the missle starting point (bot/mid of screen 53805), and a counter to keep track of the missle. Start with MM = IM (moving missle = initial missle).
Line 130 shoves the missle off
Line 140 checks to see if the missle needs to be moved. It puts a blank in the current memory location, increments the location by adding (or subtracting) the number needed to get to the next spot and then POKEs the missle in the new position.
54248 is the upper left hand corner of the screen. Line 150 resets the miss Ie position to its initial position (IM) as soon as it tries to pass that boundary.
Line 160 anticipates the hit and calls the explosion routine in line 300. Not sure that POKE IM, 65 does.
SLIDE 40: 300-340 is a sound and score routine. I forget some of the logic here, but mostly you’re formatting the screen display of the score to allow for two targets and allow for negative numbers (if you miss and that detracts from your score) by moving the number over by one place for the negative number sign.
340 blanks out the target (DI = 32). Returning to line 110 where the phrase DI = 237 turns the target back on.
345 increments the score
SLIDE 41: Use variable names rather than actual values in display statements. Every time BASIC finds a number in a program line,
it has to translate the number from its ASCII representation to a binary coded floating point value. Set variables early in the program and use the variable later. 10-25% speed improvement
Remember that variable tables are arranged in the order that the variable are seen in the program and that the variable
tables are only searched for until the needed name is found, most used in front.
Avoid remark statements in the middle of display sections, put them in the code in such a way that they’re not actually read during execution. if you number a remark 499 and GOSUB 500, the remark is obviously related to the subroutine, but is never seen by the system.
SLIDE 42: If you are going to do one thing if a value is over 100 and another if the value is e ual to or less than 100, test only for over 100 and assume the result if that test fails. Put the least likely condition last
Display cheats - moving a projectile or target two spaces at a time while moving others sequentially – your eye will not catch this.
If you are displaying a paddle several pixels wide, blank only the last pixel / end you’re displaying it moving away from.