Since the Isetta supports instructions of the Z80 processor, it also supports the famous 8080 processor, because the Z80 has the 8080 instruction set as a basis. The 8080 is interesting because it is the grandfather of almost all INTEL CPU's for personal computers of the past 40 years.
One of the very first personal computers was the Altair 8800 from the company MITS. It was built around the 8080 processor. Bill Gates, Paul Allen and Monte Davidoff created a BASIC interpreter for this computer, the Altair BASIC. It was called a 4KByte BASIC. But the actual program was smaller than 4K, because 4K was all memory that the Altair had ! There were only 790 bytes free for user programs ! Altair BASIC was the very first product of Microsoft !
So I used this Altair BASIC to test the 8080 instructions on the Javascript emulator of the Isetta processor. I found an Annotated disassembly and a binary version. And I really needed the disassembly, to understand a little of the program.
Subtract and compare
After the first tests, I found that for the 8080/Z80, the carry flag behaviour for the subtract and compare instructions is inverted w.r.t. the behaviour in the 6502. I created a new microinstruction that complements the carry flag for the 8080/Z80. In several situations, it can be executed at the same time as another microinstruction.
Parity flag
Altair Basic has a FCompare at 0A4C that compares two floating point numbers. It returns
one of the following values:
- 0x00 for zero
- 0x01 for greater than zero
- 0xFF for less than zero
That's very logical. Now you can simply test the sign flag or zero flag to jump according to the result.
But in two instances, at 0B63 and 0C03, it is followed by a JP PO (jump on parity odd) instruction, that will jump if the result is greater than zero (as 0x01 is the only one of these three values that has an odd number of '1' bits in the byte)
On the 8080, (almost ?) all arithmetic and logic instructions that act on the accumulator will
set the P flag according to the parity.
But on the Z80, the parity flag behaviour is different. Logic instructions will set the flag according to the parity, but the arithmetic instructions will set the flag when there is an overflow. And indeed, it has been reported on the Internet that the Altair Basic will not work on a replica Altair that has a Z80 processor instead of the 8080 in the original Altair.
So, although it is widely believed that the Z80 can run all programs intended for the 8080, this is not true because the behaviour of the P/V flag is different.
And on the Isetta it is also a problem because parity is not implemented at all.
The parity flag is tested with JP PO on only two occasions, at 0B66 and 0C04. Both instances are preceded by a call to FCompare at 0A4C. I replaced the calls to FCompare by a new subroutine, that does the following:
- Call the FCompare function at 0AC4
- Return if result is non-zero
- Save Accumulator
- Load Accumulator with 0xFF, and OR A to set the sign flag
- Restore Accumulator and return
Both JP PO instructions are now replaced by JP P (jump if positive). The parity flag is not needed any more (at least not for this BASIC).
A nasty bug
Strange thing were going on. The display of numbers displayed the first digit as a letter. And with another test program (TRS-80 Basic), identifiers were not recognized. After a few days, I found out that the carry flag was not cleared after an XOR A,A instruction. The microcode seemed ok, it said the carry was written (and at the same time a load operation was done). But for the carry-complement (for subtract and compare) I changed the behaviour such that writing the carry while doing a load resulted in a complement-carry ! Sometimes it is difficult to program your own contraptions.
Other changes to the BASIC
The code at the following positions was changed for character output and keyboard input:
- The code at 0377 that handles character output
- The code at 0382 that handles keyboard input
Another thing was, that this basic is full of self-modifying code. I found that when the program is initializing, it somehow seems to find out at which I/O ports the character I/O is, and writes the I/O addresses directly into the instructions that do the I/O ! So these initialisation code was changed to NOP's.
The initialization code is at the end of the program. After initialization, this code is overwritten by the user's program.
After all is done, we see the following:
At startup, the user must tell what the memory size is, and how many characters will fit on a line of his display (or printer). It then asks if you want certain functions to be available. If you say 'N', these functions will be overwritten by your application program (providing more free bytes).
A small test program:
Yes, it does floating point ! If want to know what it can do look in the Altair BASIC reference manual. And if you program in this basic and encounter a problem, some help is never far away:
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
http://www.vintagecomputer.net/cisc367/DrDobbs%20Apr%2076%20Minol%20Listing%20w-corrections.pdf
Are you sure? yes | no