26

How often was C used to program firmware for 8-bit processors in the early 80s?

I'm reverse engineering a firmware binary for a device built around a Hitachi 6303 processor, manufactured in 1983. Even though I'm new to this architecture, it's simple enough that the assembly can be easily read and understood. As I'm slowly documenting the various subroutines I'm wondering how likely it was that the firmware was originally programmed in C, as opposed to hand-written assembler. Ordinarily I would assume that the program was written entirely in assembler, however the book I'm working with The HD6301/HD6303 Series Handbook (1989) contains an entire section related to programming for this architecture in C.

14
  • 3
    How large is that firmware binary?
    – chthon
    Sep 23, 2021 at 9:36
  • 4
    While there weren't a lot of consumer-oriented programs written in it, Forth was a language almost universally available early in an 8-bit CPUs life. You'd likely realize quickly that the program flow didn't seem "normal" while disassembling a Forth program, though.
    – RichF
    Sep 23, 2021 at 14:00
  • 17
    It seems like it should be pretty easy to distinguish compiler-generated code from handwritten assembly, especially for a compiler of that vintage whose optimizations would not have been as strong as those of today. "Silly" inefficiencies in the code, rigid adherence to calling conventions, using memory when registers would have done, constant use of stack (and stack frames), no subroutine ever returns more than one value in registers, and so on. Sep 23, 2021 at 14:46
  • 4
    Related: Why do C to Z80 compilers produce poor code? - besides compilers back then being much less sophisticated at finding optimizations, some early machines were just not good C compiler targets, e.g. no stack, and/or efficient memory addressing being static array + 8-bit offset, not efficiently supporting C pointers. (And with optimizers sometimes too dumb to turn pointer code into something the machine could do efficiently, amplifying the badness @NateEldredge mentioned.) Sep 24, 2021 at 10:41
  • 3
    Note that the 6303 (and 6809 it extended) wasn't your normal 8-bit CPU, but could very well run a real OS and high-level languages. It has stack-based addressing and is designed for re-entrant and position-independent code. You are far more likely to find it was written in high level language than for other CPUs as Peter notes.
    – JDługosz
    Sep 24, 2021 at 16:24

9 Answers 9

35

How often was C used to program firmware for 8-bit processors in the early 80s?

It would have been a rather unusual choice in 1983. True, C was slowly creeping in, but only on 'big' machines and 16 bit.

If a high level language was used at all, then it was more likely some PL/1 derivation or maybe a BASIC compiler. Especially the later was rather common on more complex 6800 projects.

[...] Handbook (1989) contains [...] C.

Well, that is 1989, 6 years later than the device (*1), when C had gained a noticeable foothold.

Keep in mind, these were the 80s, when every year delivers more changes to computing, especially at the lower end, than nowadays a whole decade brings.


A Short Look at the Transition to C in Time

To put this into perspective (*2), the first Microsoft C compiler, which was not even K&R compliant, came 1983 and wasn't their own development, but a relabeled Lattice-C. It wasn't until 1985 that MS finished one of their own (MS-C 3.0).

For common 8 it systems, BDS C for 8080, of 1979, might have been the first, followed by Small-C in 1980. Both kinda limited systems, more like proof of concept. The first major commercial product I can think of would be Aztec-C in 1982. Eventually the 8 bit compiler for desktop systems (*3) - and that was what C was targeted at in the beginning. As alternative to build in BASICs and PASCAL - which was the coming language of the 1980s. Just think Turbo-Pascal.

Which is a good keyword here, as Borland was, at least during the 80s, quite good in delivering what the marked wanted. Still, their Turbo-C only came in 1987.

Another good marker might be Apple and their Mac series. All Lisa and later all classic Mac system software and most applications were written in Pascal. Yes, this includes explicit the OS. It wasn't until 1987 that Apple even included a C interface (and compiler) to MPW. Pascal Support was, way into the PowerPC age the way to go.

The second half of the 80s is when C became a somewhat relevant language in microprocessor programming, one that made sense to support (like in that data book). And it wasn't until the very late 1990/early 2000s that C - or better C++, became the first stop for many areas.


Now, for your actual project way more information would be needed to decide - starting with CPU, System and Size but as well why you assume it's HLL in general and C in particular. More likely I'd say the assembler used was macro equipped and a library (*4) of structure and data macros was used. The resulting code may quite like coming from an HLL - after all a compiler doesn't do much different by modifying and stitching code sniplets.


*1 - The product also had some development time, so language decision must have been way before 1983.

*2 - This is about C becoming a the one language across platforms, supported by essentially every CPU, OS and development tool, one that had to be supported, in ubiquitous use from embedded 8 bit to supercomputing. It is not about usage at all, as there have always been forerunners, individual users and projects using non mainstream product - which C was clearly before becoming so prevalent that people assume, without further research the language to be used to generate code.

*3 - Which BTW is opened up by now and well archived.

*4 - Guess what we called 'A Library' would be today called a framework and a documentation loaded with more 3 letter words than assembly instructions used.

1
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Chenmunka
    Sep 28, 2021 at 17:23
14

I was programming full-time on Aztec-C (for Z-80s) starting in mid to late 1982. Our target systems were embedded devices using STD-Bus. We used CP/M as a dev environment. The company also had business systems (mostly written in C) that ran on CP/M (my team would get pulled in when they'd get lost). Those systems used the full 64k, and swapped memory in and out (using overlays) to extend it. Our (embedded) systems were anywhere from 16k EEPROM and 16k RAM to 32/32. We did things like write a 3.5 kB subset of the standard C library so that we had strlen, strcat and a stripped down sprintf that we could use.

Eventually, I wrote a very simplified real-time monitor we could use in our code (it was really just a big event loop). Elements of the core were written in assembly language, and there were I/O stubs written in assembly as well. Almost everything else was written in C. People would blanche when I showed them some C that ran at the interrupt layer (really tiny bits of very well-tuned C).

Debugging was a pain. We ended up paying a small fortune for an in-circuit emulator that gave use the ability to set breakpoints and single step (at the op-code level) through our code. Initially, we'd do this using a map file to resolve symbols. We eventually got a symbolic capability within the emulator. Luckily, Aztec-C was stupid (it had nothing in the way of optimization). I got to the point where I could look at a block of code and say "OK, that's the for loop, this is the assignment and then the function call".

The dev environment was interesting. We'd edit and compile on a terminal running CP/M. Our output was packaged as a normal CP/M COM file (which is just a COre iMage file - addresses in the file mapped 1:1 to addresses in memory). When we wanted to test, we'd run our COM file - it would blow away the "OS" and take over the machine. When we wanted to get back to the dev environment, we hit the reset switch and reboot back.

It sure felt mainstream to me at the time.

Anecdote: This was our standard platform for factory floor embedded devices (Z80s, off the shelf STD-bus hardware, and C code). We were in Canada and associated with a related company in the US. Their standard equivalent was a home-designed 6800 all-in-one motherboard with all the code in assembly language. Our hardware cost more, but we could turn out the software in no time at all. The two companies got bought by a much larger company and there was a desire to standardize things. So I got up in front of management and made my case. At one point, the president of the now combined company (not the parent) interrupted and said "My people tell me that writing in assembly language is much more efficient and error-free compared to writing in C". I had no idea how to tell him he was an idiot, so I babbled about lines of code and programmer output.

6
  • 1
    Mind you, the whole story is anecdotal, as it describes your experience at your company at that time, using a brand new compiler. Also, I did still prove in the 90s to be able to program faster in Assembler than other teams in C. After all, as soon as one leaves the 'Hello-World level, it's way more about framework and experience than any particular language, isn't it?
    – Raffzahn
    Sep 23, 2021 at 19:08
  • 5
    I can assure you that by the time we had that real-time-ish library in place, we were much faster in C than we had been in assembler (more than 2x). But, yeah, anecdotal. We didn't have the internet to share experiences, we just had Byte Magazine. But, as I said It sure felt mainstream to me at the time.
    – Flydog57
    Sep 23, 2021 at 19:12
  • 5
    Another anecdote. This was my first job. During the interview (on a Thursday), my soon to be boss asked "so, do you know C". Of course I answered "yes" (I had heard of it, after all). They phoned back with an offer a few hours later. I headed out to a bookstore. By the third store I visited, I was the owner of an original edition of K&R (the pre-ANSI version). I spent the weekend reading the book and started the following Monday
    – Flydog57
    Sep 23, 2021 at 19:17
  • 5
    Nope. I was a freshly minted Chemical Engineer with some graduate work in Process Control. The only programming courses I had taken was "Fortran for Engineers" (mostly numerical analysis) and the inaugural "Microprocessor Programming" (6800) as an elective. I knew of Unix and C because of a friend in computer science.
    – Flydog57
    Sep 23, 2021 at 19:54
  • 3
    Thanks for the great stories! It's very interesting hearing about the software engineering methodologies of yesteryear. I feel a bit spoiled working on today's systems!
    – ajxs
    Sep 23, 2021 at 22:45
8

In my experience, 1983 would be possible but a little on the early side for people to be doing systems programming in C on 8-bit machines. I had summer jobs in 1982, 1983, and 1984 at Digital Research Inc., which was a fairly big systems house in Pacific Grove, CA, that sold operating systems such as CP/M and MP/M, and also sold compilers. The summer of 1984 was the first time that I started hearing any buzz about C for that type of purpose. Earlier, the perception was that it was a language used on Unix timesharing systems. DRI's own software tended to be written in either assembly language or PL/M. They had a PL/M compiler they had bought or licensed from someone else, and they were very happy with its performance and code generation. (I think it may have actually been a cross compiler that ran on a VAX or something.)

By 1983, DRI was selling a C compiler, which they had actually bought outright from someone else. This was not their usual custom, but nobody at the company had even worked with C, and I guess they wanted to have the compiler in their product line, because some customers wanted it. People complained that this compiler was slow and generated low-quality code.

In 1984, a couple of Japanese programmers had come over and were working at DRI in California, and they were considered notable because they were sages in C -- a skill that other people on the team were just starting to learn. I remember one of the Californians describing C to me as a "glorified assembly language." He said this not entirely disapprovingly, but it was definitely considered minimalist compared to baroque languages like PL/I, which had been more in style, and it also did much less abstraction away of the hardware. This was an era when people would actually use the register keyword, and people would write their own .h file that would #define WORD16 int.

In this same year, DRI started work on a redesign and rewrite of their OS, which I worked on for about a month. Both the core of the OS and the command-line utilities were in C, rather than what they previously would have done, which would have probably been assembler+PL/M. It was known by a code name at the time, but I think it was what later became GEM.

1
  • 1
    Interesting view from inside a main player (at the time). Thanks.
    – Raffzahn
    Sep 25, 2021 at 13:37
7

Full C compilers on the 8-bit series was not widely seen, but "mini-C" and "tiny-C" compilers were fairly common. One example is the OSS tiny-C for the Atari machines or Abacus on the C64.

At the time, Pascal was still a major force, and Pascal compilers tended to be more common on the 8-bit machines. Smaller versions of Pascal/Algol were also common, like Action!

All high-level languages like these would be limited by the small stack space available, especially on the popular 6502. This is why Action! didn't use activation records, and thus lacked recursion (which also sped proc calls).

13
  • 3
    IMHO, it's too bad C didn't evolve a dialect without recursion, using a combination of directives and function types to indicate which functions should be considered reachable via certain types of function pointers, since eliminating recursion and placing objects according to what would be either their highest or lowest address on a call stack (which would be easily computable at link time in the absence of recursion, if all combinations of nested calls are presumed possible) would be much more efficient than using a stack.
    – supercat
    Sep 23, 2021 at 15:07
  • 2
    Re, "Didn't use activation records." Really? I'd have thought that if there are no activation records, then there could be no function calls. Some compilers (e.g., all the old FORTRAN compilers) allocated static activation records. They allowed function calls, but not reentrant/recursive function calls. Sep 23, 2021 at 23:15
  • 1
    This page (wiki.c2.com/?ActionLanguage) lays it out: "Runtime stack (limited to 256 bytes on 6502) was used to store return address for function calls only--that was the extent of the ACTION! activiation [sic] record. ... As ACTION! was a single pass compiler with no prototypes, you couldn't declare a recursive function anyway."
    – Jim Nelson
    Sep 23, 2021 at 23:27
  • 4
    @SolomonSlow FWIW "Did not use activation records" and "static activation records" usually mean the same thing. An activation record without a stack is no different from global variables. What you name this kind of architecture depends on your point of view.
    – slebetman
    Sep 24, 2021 at 4:19
  • 1
    @SolomonSlow: In early FORTRAN compilers, all variables--and even the space used to hold function return addresses--was static. A function's caller would store or patch a jump to the desired return address immediately before a function's entry point, and a function would return to its caller by fetching an address from a spot directly before its own entry point. This wouldn't work for code running from ROM, but compiled code was never run from ROM in the early days.
    – supercat
    Sep 24, 2021 at 15:23
3

The Hitachi 6303 is unlike typical 8-bit CPUs of the era, and is in fact suitable for high level language programming and C in particular. It has a stack that can hold local variables. Subroutines are entrant, and parameters are passed on the stack. It supports 16-bit pointers that can point anywhere in memory. It has a fairly orthogonal instruction set and primitive compilers can easily generate code for it.

It's not fair to compare it with computers like the Spectrum or the C-64. Rather, look at the Tandy Color Computer with its more Unix-like operating system OS-9.

It's quite possible that a bespoke simple high-level language could have been used in-house, allowing expression statements with general arithmetic, variable assignments, function calls, etc. In short, such a language would be very similar to K&R C (maybe even inspired by it) even if it wasn't 100% compatible with it or carefully getting all the detailed semantics the same.

2

A personal anecdote: My first computer book in 1981 was called "Programming the Z80". It was focussed on assembly. I had learned Fortran in school but the main language for my home computer was Basic. Assembly was necessary for joystick and keyboard commands for a game I made. As a language, Assembly on the Z80 felt so fast but also terrible to program in given how primitive it was. I never heard about C until years later.

4
  • 2
    Just to add another anecdote; if my memory serves me, I learned the basics of C swapping floppies on an Apple //e circa 1985 or 1986, but I don't remember the name of the compiler or who it was developed by.
    – Geo...
    Sep 24, 2021 at 14:27
  • @Geo... most likely Aztec-C. It was the most common C-Compiler for home/microcomputers, including the Apple II.
    – Raffzahn
    Sep 26, 2021 at 22:20
  • I thought I was the only one. I bought the Aztec C Compiler for the Apple II when it came out in 1982 so I could teach myself C. IIRC, there was one disk for your source code, another one for the compiler and yet another for the linker (plus some library disks). It was painfully slow, and the error messages were either incomprehensible or missing altogether. It drove my partner crazy since I was whining about it every day for months. One semi-amusing side note follows.
    – Bob Ray
    Jan 25, 2023 at 19:25
  • As a side note, I called Manx to get the function for clearing the screen on the Apple II. They said there wasn't one because they couldn't know what kind of terminal was attached to the computer. I think it's a fairly safe bet that no regular user has ever connected a terminal to an Apple II. The Beagle Brothers "Peeks, Pokes, and Pointers" poster eventually saved me hours of frustration. I still have it.
    – Bob Ray
    Jan 25, 2023 at 19:28
2

I worked in 1984-86 on CAD software for 6502 machines. We did our coding, assembling and linking on CP/M, and wrote a few utilities in C for the CP/M side during 1984. It was probably Aztec C, and using that for firmware would have have been rather brave, but C compilers were definitely around. Microsoft may not have had one until later, but they weren't necessarily technology leaders at the time.

2

A quoted comment (by lloyd 2019-02-05 12:54 UTC) from an interesting article about the 6303, MC3 - A DIY 8-bit computer (emphasis is mine):

I used those same '80s processors a lot and still find much to like about them, especially the 6303's instruction set which was a joy for assembly programming. skipp, that repeater manual's a labour of love!

Can't help with a C compiler I'm sorry. In those days Pascal was more popular and it's possible only Hi-Tech was a serious effort for C on the 6303. The current chip I've found with the nearest architecture is the STM8, but the FOSS SDCC compiler for that doesn't target the 6303 or even the 6801 AFAIK. The site below has Hi-Tech for CP/M - can't see a DOS version there but it'll run in an emulator. It's Z80-focused, so maybe it didn't yet support the 6303:

https://github.com/serge-404/HI-TECH-C-V3.09

A direct link to the comment isn't available, unfortunately - you'll have to search the page, it is about 80% down.

1
  • 1
    done, please see edit. Please flag this comment for removal once you've seen it. Sep 27, 2021 at 0:25
1

I started programming 1984 on a Sinclair (Farewell, Sir Clive!) ZX Spectrum, (which was invented two yeas earlier). Around 1983 was the start of the golden era of 8-bit "home computers" like the ZX spectrum, the C64, Ti99/4A, the BBC computer etc., and the Apple 2e.

Keep in mind that those computers had 64k or less RAM (the ZX81 had 1K, the ViC 20 hat 5K, the Spectrum had 16K or 48K).

Typical CPUs were Z80A (Spectrum) and 6502(?) (C64)

Owning such a thing became affordable at that time (I remember I paid 498 DM for the Speccy, the C64 would cost 700 DM).

Most people just played games, but you could also program quite well. The machines usually had a BASIC interpreter built in (in ROM), and BASIC was easy to learn, so it was common to program in Basic.

With the Speccy came a hand-book which explained the whole thing, including a BASIC programming course with examples, all system settings, and all Assembler Op Codes.

BASIC was terrible slow, so if your wanted a program to run (and not to crawl), you had to use another language.

A natural choice was Assembler then, because an assembler is small enough to fit into RAM. So I used assembler to program little games or graphic routines (e.g. drawing lines and circles much faster than with the built-in commands).

I also looked out for alternatives then and I can't remember to have seen a C compiler. Instead, alternatives (for the Spectrum) that I remember were:

  • Beta Basic (it was way cool at that time)
  • Forth (White Lightning)
  • Pascal (not sure here, it was quite unusable IIRC)

On other machines there were languages like "Action!" (for the Atari 8-bit computers).

There certainly existed C compilers for the spectrum (at least a few years later), but I wasn't aware of them (and nobody I knew).

But even if I had owned a C compiler at that time, I certainly would have used Assembler instead.

Keep in mind that programs for 8-bit computers were much smaller and simpler, and more complicated routines were availabe in ROM anyway, so e.g. on the Spectrum, if you need to load a file from tape, you just had to call the existing routine.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .