norwestrzh
Experienced Member
8-bit retro-programming
8-bit retro-programming
I've been playing with some compilers that run in the CP/M (2.2) environment. Since I've finally got a stable, fast (16 MHz) homebrew Z80 SBC, with some usable tools (editors, file transport to/from the SBC, etc.), sixteen "disk" drives (on compact flash) and the time (what else is there to do on these cold, rainy, dark winter days?).
Perhaps some of you folks might find this interesting??
A piece of code that computes a Mandelbrot set and displays it using ASCII characters has been making the rounds as sort of a benchmark for small systems. It involves a fair measure of floating point calculation, so it is somewhat compute intensive, but not so much so that it takes hours to run. Typical output looks something like this:
[sorry, couldn't get the fixed width font to work properly.]
I decided to re-code the original program (written in BASIC) to test out some of the classic compilers/interpreters that were popular in the old Z80 CP/M community. I've written some BASIC and C, but it has been many years since I've written FORTRAN or PL/I. Never wrote Pascal before now (IMO Pascal is "begin ... end;" hell!). So, there may be some bad coding going on here. In particular, I had a difficult time trying to figure out how to get F80 to write out a single character with no CR/LF, so I buffered a line of the output (above), and coughed it out as a single ASCII string.
Many of the compilers/interpreters were a challenge in themselves. There are often multiple versions available. Sometimes I was unable to get some of them to work at all (corrupt old files taken from my collection of old 8" and 5.25" diskettes??). Many lack good documentation, so it was hard for me to figure out how to run some of them. The table below gives the results for the ones that I was able to get working with my re-write of the program. There may be optimizers for some of these compilers (or optimization options), but I made no attempt to do any of that. Again, the documentation that I was able to find was often not very good, so figuring out optimization might have been difficult to do.
compiler/ time code
interpreter version (secs) size
------------ ------- ------ -----
Hitech C v. 3.09 20 7,808
MS F80 v. 2.7 26 12,672
MS F80 v. 3.44 27 12,928
DRI PL/I-80 v. 1.0 29 8,832
Borland TP v. 3.0 39 8,704
DRI MT+ Pascal v. 5.6.1 32 25,728
MS BASCOM v. 5.2 29 9,472
Nevada FORTRAN v. 3.0 70 725 *
MS MBASIC v. 5.21 71 n/a
BASIC-E v. 2.1 68 n/a **
_________________________________________
* Nevada FORTRAN produces a .OBJ file which is run by using their FRUN.COM program. It may well be that the .OBJ file is a tokenized version of the FORTRAN
code? It is not a stand alone .COM file, so difficult to compare with the other compiler generated executables.
** 2 step process: tokenizes the BASIC source, and then executes the tokenized file in interpretive fashion. Time given is for execution phase only.
_________________________________________
Clearly, Hitech C is the overall winner for both code size and speed. [As a frame of reference, my homebrew 18.4 MHz 68000 runs a cross-compiled C version (output from GCC) in about 13 secs.] However, the other compiled versions (FORTRAN, PL/I, BASIC, and Pascal) seem to be clustered right around 30 secs., with not a whole lot of execution speed variation. They perform similarly, and relatively well! I did not expect that. I found it surprising that Turbo Pascal had the slowest execution time of all the compiled code, although it produced a fairly compact .COM file. There is, however, lots of variation in code size amongst the other compiled code. The one outlier is Nevada FORTRAN. I have no idea how it works, internally, so it is difficult to categorize. It may be a hybrid between compiler and interpreter, and that may account for the execution time that is more like that of the interpreters. And finally, it probably ought to be no big surprise that the execution speeds for the BASIC interpreters (last 2
lines in the table) are quite a bit slower.
I'd like to see how FORTH would compare with the above times, and I know that there are at least Algol and Modula2 compilers available for CP/M 2.2. BUT, it would probably take me longer than the current lock-downs will persist, to figure out how to code this application in those languages.
P.S. -- Couldn't resist! I've been playing with a new (very tiny) microcontroller from Adafruit, called the QTPy. It is a 32-bit ATSAMD21E18 Cortex M0+ CPU running at 48 MHz, and only about the size of a postage stamp. The native firmware is CircuitPython, so I coded this application in Python. It runs in about 9 seconds on the QTPy. I wasn't able to find a CHR$ work alike in Python, so I had to do a character lookup from an ASCII string in order to print out the ASCII display.
8-bit retro-programming
Hey guys,
I feel like I don't hear enough about how other retro-programmers work, I was wondering what you guys were all using for your retro-programming needs.
What hardware are you targeting?
What kind of compiler/interpreter software do you use?
Do you program on old-school systems themselves or do you use a modern editor?
And (hopefully without starting a flame war) what language(s)?
Right now, I'm writing for an old AST 286 PC machine.
I use the OpenWatcom Compiler.
I use a modern PC with Visual Studio as my editor.
And I use C++ and some 8086 assembly, with a dash of a custom scripting language.
How about you guys?
I've been playing with some compilers that run in the CP/M (2.2) environment. Since I've finally got a stable, fast (16 MHz) homebrew Z80 SBC, with some usable tools (editors, file transport to/from the SBC, etc.), sixteen "disk" drives (on compact flash) and the time (what else is there to do on these cold, rainy, dark winter days?).
Perhaps some of you folks might find this interesting??
A piece of code that computes a Mandelbrot set and displays it using ASCII characters has been making the rounds as sort of a benchmark for small systems. It involves a fair measure of floating point calculation, so it is somewhat compute intensive, but not so much so that it takes hours to run. Typical output looks something like this:
[sorry, couldn't get the fixed width font to work properly.]
I decided to re-code the original program (written in BASIC) to test out some of the classic compilers/interpreters that were popular in the old Z80 CP/M community. I've written some BASIC and C, but it has been many years since I've written FORTRAN or PL/I. Never wrote Pascal before now (IMO Pascal is "begin ... end;" hell!). So, there may be some bad coding going on here. In particular, I had a difficult time trying to figure out how to get F80 to write out a single character with no CR/LF, so I buffered a line of the output (above), and coughed it out as a single ASCII string.
Many of the compilers/interpreters were a challenge in themselves. There are often multiple versions available. Sometimes I was unable to get some of them to work at all (corrupt old files taken from my collection of old 8" and 5.25" diskettes??). Many lack good documentation, so it was hard for me to figure out how to run some of them. The table below gives the results for the ones that I was able to get working with my re-write of the program. There may be optimizers for some of these compilers (or optimization options), but I made no attempt to do any of that. Again, the documentation that I was able to find was often not very good, so figuring out optimization might have been difficult to do.
compiler/ time code
interpreter version (secs) size
------------ ------- ------ -----
Hitech C v. 3.09 20 7,808
MS F80 v. 2.7 26 12,672
MS F80 v. 3.44 27 12,928
DRI PL/I-80 v. 1.0 29 8,832
Borland TP v. 3.0 39 8,704
DRI MT+ Pascal v. 5.6.1 32 25,728
MS BASCOM v. 5.2 29 9,472
Nevada FORTRAN v. 3.0 70 725 *
MS MBASIC v. 5.21 71 n/a
BASIC-E v. 2.1 68 n/a **
_________________________________________
* Nevada FORTRAN produces a .OBJ file which is run by using their FRUN.COM program. It may well be that the .OBJ file is a tokenized version of the FORTRAN
code? It is not a stand alone .COM file, so difficult to compare with the other compiler generated executables.
** 2 step process: tokenizes the BASIC source, and then executes the tokenized file in interpretive fashion. Time given is for execution phase only.
_________________________________________
Clearly, Hitech C is the overall winner for both code size and speed. [As a frame of reference, my homebrew 18.4 MHz 68000 runs a cross-compiled C version (output from GCC) in about 13 secs.] However, the other compiled versions (FORTRAN, PL/I, BASIC, and Pascal) seem to be clustered right around 30 secs., with not a whole lot of execution speed variation. They perform similarly, and relatively well! I did not expect that. I found it surprising that Turbo Pascal had the slowest execution time of all the compiled code, although it produced a fairly compact .COM file. There is, however, lots of variation in code size amongst the other compiled code. The one outlier is Nevada FORTRAN. I have no idea how it works, internally, so it is difficult to categorize. It may be a hybrid between compiler and interpreter, and that may account for the execution time that is more like that of the interpreters. And finally, it probably ought to be no big surprise that the execution speeds for the BASIC interpreters (last 2
lines in the table) are quite a bit slower.
I'd like to see how FORTH would compare with the above times, and I know that there are at least Algol and Modula2 compilers available for CP/M 2.2. BUT, it would probably take me longer than the current lock-downs will persist, to figure out how to code this application in those languages.
P.S. -- Couldn't resist! I've been playing with a new (very tiny) microcontroller from Adafruit, called the QTPy. It is a 32-bit ATSAMD21E18 Cortex M0+ CPU running at 48 MHz, and only about the size of a postage stamp. The native firmware is CircuitPython, so I coded this application in Python. It runs in about 9 seconds on the QTPy. I wasn't able to find a CHR$ work alike in Python, so I had to do a character lookup from an ASCII string in order to print out the ASCII display.