For reasons I’ve talked about in other areas, I’ve
no longer too lengthy within the past turn into all for the exercise of, and programming, CP/M all all over again,
after an interval of 40 years. I’ve even offered a true,
Z80-primarily primarily primarily based, CP/M machine to experiment with. There is a little, but
rising, market for these machines amongst retrocomputing lovers.
I’ve applied a host of contemporary utilities for CP/M in C —
keep in mind, for example, KCalc-CPM, cpmbox,
and cpmlife.
cpmlife became as soon as applied the exercise of a contemporary Z80 unpleasant-compiler,
but I in actuality feel that a technique or the opposite this is dishonest. If I shuffle to manufacture for
CP/M, I for experience ought to exercise CP/M instruments. I could unbiased no longer close the total growth
or attempting out on CP/M — on account of or no longer it’s reasonably time-involving — but
I savor to know that it’d be that you just have to imagine to construct my code
fully below CP/M.
This article is about rising in C for CP/M, the exercise of a 40-year-former
C compiler, and how this differs from contemporary C growth.
The compiler I’m the exercise of is the 1982 free up of Manx Tool Programs’
“Aztec C”. The compiler is freely, and legally, accessible from
the Aztec Museum.
A kind of CP/M tool falls into the colossal class of “abandonware”
— tool that is notionally restful stable by intellectual
propery regulations, but whose homeowners assemble no longer salvage any hobby in it, or cannot even
be acknowledged. In the case of Aztec, nonetheless, the homeowners of the
intellectual property, whose utter is no longer in dispute,
salvage talked about that they’re happy for it to be
allotted and historical.
About Aztec
The Aztec C compiler would salvage within the launch be allotted on floppy
disks, and is extraordinarily little by moden standards. The compiler, assembler,
and linker are every about 20kB in size. The C library and the arithmetic
library are reasonably bigger.
The compiler outputs assembly code, which need to be assembled one by one.
Trendy C compilers typically can generate assembly code, but this is
ceaselessly an internal operation, no longer considered to the user. The Aztec
C compiler for CP/M for experience generates 8080, no longer Z80, assembly directions,
so this is in a position to perhaps unbiased work on both CPUs — the Z80’s instruction self-discipline is a cumbersome-self-discipline
of the 8080’s. This does imply, nonetheless, that the extra sophisticated
parts of the Z80 instruction self-discipline assemble no longer fetch historical. There seems to be to be
a z80-particular compiler in later Aztec releases, but I haven’t been
ready to fetch it to work.
After the compiler has produced an assembly language “.asm” file, the assembler
converts this to a binary object file. Object information play precisely the
similar feature here as they close in contemporary C growth, but they’re no longer in any
recognizably contemporary format. The linker than combines the item
information with the customary library to manufacture an executable.
So the sequence of operations for compiling hello.c
to an executable is:
A> cc hello.c
A> as hello.asm
A> ln hello.o c.lib
Show off:
CP/M is broadly case-insensitive. The textual state ‘hello.c’ will likely be offered to the compiler as ‘HELLO.C’ no subject the usual case. There is no evident formulation to manufacture a decrease-case filename on CP/M
Unless instructed in any other case, the linker will assemble a binary with the
similar title because the first of its arguments; in this case,
hello.com.
The Aztec compiler pre-dates ANSI C, and follows the broken-down
Kernigan & Ritchie syntax. Essentially the most evident distinction from contemporary
practice is in feature declarations:
int my_function (a, b)
int a; char *b;
{
… physique of feature …
}
Trendy C compilers will settle for this syntax, which will likely be precious in case you
salvage to envision a part of a CP/M C program the exercise of contemporary instruments — extra
on this later.
Variables need to be strictly declared on the launch up of a block, which
ability that every opening brace “{” is commonly followed by a slew
of declarations. Trendy practice favours striking declarations nearer
to where the variables are historical. Right here is utter relevant for
trivial loop regulate variables. You could be ready to’t write this:
for (int i = 0 i < 10; i++)…
You’ve to jot down this:
int i;
…
…
for (i = 0 i < 10; i++)…
Right here is undeniably a nuisance, but no longer an colossal mission in most instances.
A bigger mission is the shortcoming of any const modifier,
both to mask fixed quantities or fixed pointers.
This makes bring collectively-time error checking less thorough. I’ve stumbled on that
a host of mistakes that could be seen at bring collectively time by a contemporary
compiler assemble no longer fetch picked up by the CP/M compiler. After all, this
annoyance need to be regarded as alongside the undeniable fact that the total
compiler is simplest 20kB in size.
Characteristic prototypes
The Aztec compiler doesn’t give a grab to chubby feature prototypes,