Memories of a ‘bare-metal’ programmer
By Luigi Logrippo
Started January 2007 – Last updated April 2019.
The Olivetti Elea 9003 was the first industrial electronic computer made in Italy. The first 9003 was completed in 1958 and its commercial announcement was made in 1959. The first operational specimens were installed in 1960, and the last in 1964. About 40 were produced. Its predecessors, the Elea 9001 and 9002, were not for sale and used vacuum tubes.
For those who want to know a lot about the Elea 9003, and can read Italian or are willing to go through Google Translate, here is the Programmer’s Manual (pdf, 128M). For those who just want to browse, the manual includes some interesting pictures.
The Elea 9003 CPU was entirely transistorized, but not integrated. In fact, there were approximately 300,000 components in a typical system, between transistors and diodes. In the RAM module, each bit was stored in a ferrite ring (a core, hence the first meaning of the term core memory). The diameter of each core was approximately mm. 1 and each core was crossed by 4 copper wires. A character consisted of six bits with an additional parity bit (the latter not visible from program), so a memory module of 10,000 characters required 70,000 cores –and each was threaded manually! The size of such a module, with the addressing circuitry, was of approximately cm. 50x45x20. The ‘periodo di cifra’=memory cycle (access to one character for reading or writing) was 10 microseconds, thus the machine’s speed was 100KHz. This was fairly standard technology around 1960, in fact initially somewhat ahead of other competing systems.
Just as other computers of the time, this one was a… dinosaur. It occupied large, air-conditioned rooms. It consisted of a series cabinets interconnected by overhead wiring, each about 1.5 meters high. A cabinet included main memory and CPU (additional cabinets were required for memory extensions). A second cabinet was the control unit for the tape units. A third cabinet would contain the control unit for other peripherals such as the printer. The tape units and the peripherals themselves were quite bulky. Happily, the machine looked good because it was designed by a famous architect, Ettore Sottsass. Several pictures are available on the Web.
It has been claimed that this was the first fully transistorized commercially distributed computer in the world. This claim is difficult to substantiate for a time when all computers still contained some vacuum tubes (I believe that the 9003 had some in the power system). IBM had announced a fully transistorized system 608 in mid-1955, however it is unclear whether this one should be relegated to the category of punched-card equipment: it was programmed from a patch-board and it was extremely limited in terms of memory and number of program steps. The Metropolitan-Vickers MV950 of 1956 has been cited as the first transistorized computer to become commercially available. Siemens had announced a fully transistorized System 2002 some months before the 9003. IBM transistorized mainframes followed months later; in fairness, it must be said that these were shipped with a good set of software tools from the start, which was not the case for the Elea. However surely the Elea 9003 was among the very first in the world in this category. And Olivetti management showed a lot of vision and courage to bet on transistor technology at a time when leading computer manufacturers were still selling vacuum tube technology.
A variant of Binary-Coded Decimal (BCD) representation was used for addresses and data. The basic storage unit was the ‘character’. With six bits per character, there were sixty-four possible characters. However the binary encoding of numeric characters was not the usual one: e.g. 2 was 000011, 3 was 000111 (see programmer’s reference card).
The decision of using decimal, rather than binary, representation of numeric quantities and addresses was friendly to programmers but created some problems. For one, numeric quantities required more bits than necessary for binary representations, since numeric characters had two bits (of six) that were always 0. This is normal in today’s large memories but had consequences in the memory sizes of the times. In addition, if the addresses could only be numeric, the maximum memory size would have been 9999. In order to allow addressing the second memory bank the address after 9999 was ø000, and after ø999 we had A000. Somehow, address 40,000 was 0ø00, no need to get into further details … Since the T registers were used for addresses, the arithmetic on the T registers had to give valid addresses and thus was different from the arithmetic for the accumulator. The complexity of the arithmetic unit was considerable for the time. Correspondingly, the logic of several instructions, especially those involving registers, was complicated. Even leading programmers, asked many years later, could not answer some specific questions.
Of course there was no dynamic memory allocation so each program would be loaded contiguously always at the same memory location, and would be the only program in memory during its execution. All memory was usable by the programmer, although it became usual to leave the first 3,000 characters available for testing programs.
There were no floating point representation nor floating point instructions, this computer being designed for commercial applications.
Memory size could go from 10K (one memory module) to 160K characters, with typical sizes around 40K. The CPU had an accumulator register of the capacity of 100 characters, and this was the main operating register of the programming logic. There were also 40 additional registers, called T registers, each of the capacity of 5 characters. These were mostly used as base or index registers, see below, although they could be used to store and operate on any small values.
All the instructions were of eight characters. Many instructions were of the form:
LL IIII T O
Where: LL was the length, the number of memory characters affected by the instruction, IIII were four characters of address in memory (I stands for Indirizzo in Italian), T was the address of a T register whose contents was to be added to the address IIII, O was the op code.
For example, the instruction:
12 3456 7 F
would take 12 characters starting from the address (3456 + contents of register 7) and move (copy) them to the accumulator register. So if the current content of the register 7 was 50, the characters in the memory positions 3506, 3505… to 3495 would be moved.
The 1960s were a decade of great inventiveness in terms of proposing rich instruction sets, intended to help programming common tasks. This phase in computer history came to an end with the introduction of the IBM360, which avoided complicated instructions. The Elea 9003 instruction set was fairly rich (99 instructions), and many instructions were designed to be used in ingenuous ways, which was not necessarily conducive to clear programming style. There were instructions to add, subtract, compare the content of the accumulator register to the content of memory positions. There were similar instructions for the T registers. The start positions of the accumulator and the registers could be changed. There were many jump instructions (unconditional as well as depending on several types of conditions) and some instructions that operated directly between memory locations. The list of all instructions is given in the programmer’s reference card. Some complicated I/O instructions are mentioned below.
From the programmer’s reference card it is possible to calculate the instruction execution times. As mentioned, a memory cycle in this computer was 10 microseconds. Let us consider for example a very common instruction, the MA (to transfer data from Memory to the Accumulator). The execution time for this instruction is listed as 10+L memory cycles(‘tempo in periodi di cifra’). This means, 10 cycles=100 microseconds to prepare the instruction (read it into the CPU and prepare it for execution), plus as many memory cycles as there are characters to be transferred. Hence, 150 microseconds would be needed in total to execute an MA to transfer 5 characters from memory to accumulator, 200 to transfer 10 characters, etc.
Ampex tapes were used, contained in large cabinets as tall as a person. All files were kept on tape. In fact, one way of thinking of the 9003 is that it was essentially a machine to process tape files: sorting, merging, updating, preparing and printing reports. Each tape reel was 1100 meters long with a density of 120char/cm and so it could contain a theoretical maximum of around 13M characters. Reading speed was 3.8 meters/sec corresponding to 45.6K char/sec. Typically, there would be from four to ten, up to twenty tape units. Many tape units were useful to reduce tape sorting time, allowing dividing the sequence to be sorted into a number of subsequences determined by the number of tape units available. Sorting a tape file was a major job that could take several hours (a night’s job for an operator). Interestingly, Von Neumann’s “merge-sort” algorithm, invented in 1945, was in common use, in variations such as polyphase merge sort. Of many inventions of Von Neumann, this one is perhaps one of the least mentioned; it may be one of the most commonly used, still today (if we include algorithms that were derived from it).
In the first years, the program and data would be read initially from Olivetti punched tape, later Bull card readers became standard. The console had a typewriter, an Olivetti telex machine. The console also had a keyboard from which instructions could be entered for direct execution, one at a time.
There was a line printer, made by Sheppard. It was an impact drum printer, which activated tiny hammers as they passed over characters on a cylinder. It was capable of printing 300 lines a minute. It could be programmed by means of a patchboard. For example, by appropriate connections on the patchboard, it was possible to program the printer to skip a line before printing a line with a ‘+’ at the beginning, or to start a line on column 10 when encountering the ‘%’ sign in the same position.
There was the possibility of attaching up to three magnetic drums, meant to store the most frequently used files, or as swapping devices.
One day we were shown a disk unit, a glass cabinet containing a pile of large metal disks. I believe it could contain about 300,000 characters. This was also produced outside of Olivetti.
At Olivetti, a mass storage unit was later developed consisting of large floppy disks disposed in a toroid shape around a reading mechanism, a sort of old-fashioned jukebox for those who have seen such things. When a read instruction was executed, an arm would quickly grab the appropriate disk and place it on the reading mechanism. The disks could be manually inserted and removed. The name was Miac, Memoria Intercambiabile ad Accesso Casuale.
My information is that none of these devices (drums, disks, Miac) were ever installed at customer sites for the Elea 9003. The only mass storage units were the tapes.
Computing centers that had many cards also used specialized machines to convert card files to tapes.
There were sophisticated I/O instructions, as in other mainframe computers of the time. For example, there was a tape search instruction that could find on a tape file a block containing a given character sequence (instruction PRN – Prepara Ricerca Nastro). Another instruction could read a tape block, scatter its records in main memory according to an address vector provided, and simultaneously compose (gathered) another block for writing, according to the same address vector (instruction NDN – Da Nastro seguendo una Direttrice a Nastro). This facilitated tape sorting: a block was read in, the program compared the sort keys and set the address vector, and the records were written in sorted order on the output block. Simultaneously, another block was read in the memory areas freed by the outgoing records, and so on.
The computer had a primitive interruption mechanism for I\O, as well as the concept of second and third program: up to 3 programs could run at one time. This was made possible by the existence of two Transfer Channels, the Internal (connecting memory, CPU, etc,) and External (connecting slower peripherals). . The programmer had to determine which were the first, second and third program, and had to explicitly program jump instructions between programs (S2P, S3P: salta al secondo, terzo programma). Normally, the first program would be dedicated to processing data in memory, the second program would be dedicated to fast peripherals such as tape and drums, and the third program to slower peripherals such as card readers and printers. Priority was automatically given to the third, then second, then first program. When a program became blocked for an I\O operation, a hardware mechanism assigned the CPU to another program. A program could regain the CPU after the operation it was waiting for completed. So multiprogramming, with superposition of I/O times of different devices and CPU times was possible. The scheduling of the programs was done by hardware, however the three programs had to be explicitly programmed as parts of a single program structure. Setting up this program in such a way as to optimize overall execution time was far from trivial. These possibilities were complicated to use and not well documented and thus were seldom used. It was later understood that the management of multiprogramming cannot be left to the programmers, it must be done by layers of software known nowadays as the Operating System (there was neither OS nor any BIOS whatsoever on this machine, the concepts were very new at the time).
From the programmer’s point of view, the organization in characters was a considerable advantage with respect to the more usual organization in binary words of other contemporary computers. A character on the coding sheet became a character to punch on tape or card, and in turn that became a character in the computer memory. No need to deal with octals or hexadecimals, as with many computers of the time.
fixed length of instructions was also an asset, because it made it easy to
determine the address in memory of each instruction.
The base registers enabled relative programming: for example, in a loop to fill a block of records to be written on tape, the instructions in the loop would all point to the first record, while on each execution of the loop the contents of the registers would be updated to successively point to the second, third, … record. This of course has always been a standard programming technique, but not all computers of the time had the hardware registers to facilitate it.
As mentioned, there were also rather complex features, but they could be avoided and indeed wise programmers avoided them …
When it comes to software, a painfully familiar picture appears. ‘Basic software’ R&D started at Olivetti only around 1959, as the Elea 9003 started to be marketed, and with a very small staff. At peak some years later, this staff reached a level of about 35 people for both Elea 9003 and 6001: compare this with IBM, for which there is a contemporary picture showing 25 people in the FORTRAN team only. Furthermore, the R&D group thought that their main mandate was innovation, to develop new concepts in programming languages and compilers, without considering immediate customer needs. There was no integrated planning between this group and the marketing group, in fact the two groups belonged to separate divisions that reported directly to the CEO. This was a structural fault that had fatal consequences.
So, asks Pinocchio, pray tell, who will develop input-output macros, mathematical macros, an assembler, a sort and merge program generator, a linker and a loader, testing tools, FORTRAN and COBOL? Very simple, answered the Blue Fairy, the machine is so pleasant to program that programmers won’t mind developing all the necessary programs by themselves, in machine code, over and over again for every application. Today this is called ‘programming on the bare metal’, and starting from scratch every time.
Still, some basic software was developed slowly, mostly by a handful of people in the marketing division, independent of the R&D division. By the time the Elea 9003 went out of production, this software was limited to: the assembler Psico, some testing software, and some tape merging and sorting utilities.
Initially, the main method of debugging was step-by step execution controlled from the console, looking at the contents of the CPU registers that were shown in binary on arrays of lights. One would also use small memory dumps on the console typewriter, and larger ones on the line printer. Some time later, the most commonly used debugging program became the ‘Monitor’ which could be used to print the execution of a program instruction by instruction, showing the instruction itself and the data modified by the instruction, before and after. Obviously, it used a lot of paper… Still, it may sound like a miracle today that this program only occupied 3K of memory; it was the result of machine programming virtuosity. (Incidentally, this is the reason why Elea 9003 programs usually were written to be loaded at memory address 3000). Some time later a more sophisticated testing program became available, where one could specify parameters to focus on certain sequences of instructions.
At that time it was not commonly understood that in order to justify the cost of software production, companies had to develop long-lasting and wide-ranging lines of compatible computers. The IBM 360 (introduced in 1964) was the first family of computers that was based on this idea. At the Olivetti R&D labs the same problem was addressed with research on high-level languages that would eventually became common to all the computers of the company, an idea that became practical several years later with the language C.
Not much was known about programming at that time. Some programming manuals in English existed, but they were machine-specific, since high level languages were just being invented. Programmers were mostly graduates from technical schools who were given a five to ten week course on machine language and flowcharting (see flowchart template). Our first chance to work with a computer and run programs would come after the course, sometimes much after. As we waited for a first chance to use the computer, we wrote on paper and black ink code that we thought was perfect …
Programming style was most primitive. ‘Jump’ (or ‘go to’) instructions were used wholesale and went in all directions. When a program had to be modified, programmers did not dare to touch the code that had already started to work, they would rather make a ‘patch’ in the form of a ‘jump’ instruction that would go to the end of the program to the new code, and then jump back in. Later availability of an assembler (called Psico) did not change the picture much, because the assembler was slow and so programmers did not want to reassemble a program every time a correction was needed (the source program was stored on tape and each compilation took several tape passes).
Some people today might wonder how anything useful could be done with computers having such small memories. Well, some years ago I saw (Comm. ACM 48 (2), 99-101) a ‘Hello World’ program, written, according to the author, in ‘proper’ object-oriented style. It had over 20 lines of Java-like code. Its execution (let alone compilation) would involve the execution of untold numbers of machine instructions, including Operating System code. Granted, the same result could be obtained by a much shorter program however apparently it would not be proper OO style.
On the Elea 9003, we would program this in 27 characters (two instructions and one constant string); the rest of the memory would be empty.
11 0017 # ø Prints the memory contents from address 17 for length 11
0X XXXX # 0 Stops the program
HELLO WORLD The constant at address 17
And how to execute this program? Since it is short, we’ll type it directly in memory at address 1, so we type on the console keyboard:
27 0001 # %
Then we type the 27 characters on the console typewriter. Finally we branch to position 8, the address of the rightmost character of the first instruction, entering the following instruction from the console:
)# 0008 # O
This caused the program to be executed. In modern terminology, this was our way to bootstrap on the bare metal. Simpler times…
Well, and then we could talk a lot about the tricks so common among machine language programmers of the time. Here is a particularly daring one: since instructions were of length 8, if a program was loaded at address 1, then legal branching addresses were: 8, 16, 24, 32… BUT perhaps a program could be organized in such a way that an executable sequence could be encountered by jumping at an intermediate address, such as 27. In such a way one could have two partially overlapping programs. This trick was used in the program Monitor, mentioned above. It was later understood that program optimization can be much better achieved by using a transparent programming style.
As example of short mathematical program, I offer the attached long division subroutine (with thanks to Prof. Stefano del Furia). In the absence of loaders and linkers, this subroutine had to be copied in all programs that needed it. The addresses in the subroutine had to be manually written in at the time the program was copied. Address X was the address of physical memory where the subroutine started in the program that used it. Note that the subroutine is in the first column, the one titled ‘Istruzione’. The rest are comments.
What application types did we work on? Payrolls, inventory control, bank and insurance accounting were the bread-and-butter. Information retrieval for industrial libraries was one of my specialties. Other groups worked on Operations Research and Engineering computations. And, thinking back, it is amazing how many possibilities were being explored, which are still considered research topics now.
In the first years, the Olivetti Elea 9003 was plagued by maintenance problems. Computers were maintained every morning by a team of technicians. However by early afternoon things started to fall apart, especially in the peripherals. Was there a non-recoverable read error in a tape? Here is the fix. Perhaps the operator could still manually read in memory the block, find the affected characters and replace them with a ‘reasonable’ interpretation of what should have been there. The whole tape could then be reconstructed with the new block in place.
Computers were hard to get in the early times. A programmer of those times recollected that a janitor thought she had an identical sister, one going home at dawn and the other arriving to work at 8:30. A manager asked for explanations when she discovered that ‘the machine’ had been unused between 00:00 and 8:00 on a Christmas day.
Because of the absence of debugging systems, program debugging could be done only by programmers themselves when the machine was available, usually in chunks of few hours. This was usually at night, because in the daytime computers were used for production purposes, to execute working programs. The problems just mentioned, unavailability of software and maintenance issues, caused many frustrations.
For example, here is how programs were initially loaded for the first many months. They would be punched on paper tape, and then read by the paper tape reader. Unfortunately, this one would usually tear the tape, over and over. However before the tape was broken, a portion of the program had been read in memory… so programmers read the paper tape in memory a bit at the time, by repeatedly patching it, and then assembled the program in memory by operations entered from the console. The assembled program would then be copied to magnetic tape (itself fraught with errors). When card input became available, the Bull card readers were slow and unreliable.
Engineers usually take existing systems as models for the new products they design. They usually want to improve on something that already exists. So the question comes up, what were the predecessors of the Elea 9003? I have not been able to find a clear answer to this question. The main designers of the computer did not leave any writings. Previously to their work at Olivetti, some of them had worked with the Ferranti Mark 1, and one can recognize some of the characteristics of this machine in the design: single address, fixed length instructions, accumulator, index registers. However the Mark 1 was word-based rather than character-based.
I hope that some of my readers will be able to help. It may be possible to find similarities with other computers existing in 1957, the date of the Elea 9001.
My account of the 6001 will be shorter, because I used it much less. Also several of the observations already made for the 9003 hold for the 6001.
The Elea 6001 was designed as a smaller brother of the 9003, and as a scientific computer (it would have been very nice if it had been just a scaled down 9003… ).
Production started in 1961. About 170 were sold.
The Elea 6001 was also fully transistorized, with ferrite core memory. Memory sizes were from 10,000 to 100,000 4-bit characters, small sizes being the most common. It had a floating point representation for reals. It had a microprogramming memory (called matrice di sequenza logica, or logic sequencing matrix), which was used to microprogram mathematical functions such as multiplication, division and square root in floating point. More advanced functions had been planned, but they never got to the production stage.
The Elea 6001 memory was organized in characters of 4 bits. As for the 9003, the binary coding of the numerals was peculiar (see programmer’s reference card). Of course, only sixteen characters could be represented in 4 bits, which means that numerical digits were represented by one character, while letters had to be represented as combinations of two characters. This may be acceptable for scientific applications, where numeric and alphabetic fields are separate. It led however to the situation that alphanumeric fields, containing variable numbers of alphabetic and numeric characters, were of unknown length between a minimum and a maximum (more on this below).
Each character had an extra bit, the ‘wordmark bit’ that delimited the length of the variables in memory (more on this below). The bit was 1 if the character was the least significant character of a quantity, 0 otherwise. The bit was also used to mark the end of an instructions.
There was, of course, floating point logic.
Instructions were of varying (and variable) lengths. A typical instruction could be as follows:
OO T IIIII
Where OO was the op code, T was the name of a register (registers were used in the same way as for the 9003), and IIIII were five characters of address. The full list of instructions is given in the programmer’s reference card. A typical instruction would operate from the address IIIII + T for decreasing addresses until it encountered a character with the wordmark bit 1.
Several of the characteristics of the 6001 were difficult to manage for the machine code programmer, although they could have been used to advantage by optimizing compilers:
In addition, variable-length instructions made it difficult to calculate addresses in the program, another problem for the machine-language programmer.
It should be noted that such memory-saving tricks were not unusual in the small computers of the time (among others, they were present in some IBM computers).
Software was more complete than for the 9003, as was necessary, given the more complex programming. The software R&D division produced an assembler and a compiler for Palgo, a dialect of Algol. However the scientific programming world at that time (and for a long time thereafter) was dominated by FORTRAN. So a compiler for FORTRAN had to be produced quickly by the marketing division (by a staff of only three) a fact that caused embarrassing rifts in the company. It is interesting to note that the R&D division was historically correct, since many modern programming languages have been influenced by Algol through Pascal, Ada, C, and Java, while FORTRAN has remained almost without descendants.
At some point Olivetti realized that it needed a computer for medium-size companies and the decision was taken that the Elea 6001 would be marketed for business applications. A number of them were sold for this purpose. Given the memory structure used by the computer, I can only feel sympathy for the programmers that had to program these applications. In business applications fields are often alphanumeric, e.g. an address field punched in a card typically contains variable numbers of numeric and alphabetic characters. So a card consisting of 80 alphanumeric characters could take anywhere between 80 and 160 characters in memory (the extremes being the cases where it contained only numbers or only letters). This quantity was not known until after completion of the read instruction. Now, how to find the different fields in the card? Field lengths and memory addresses had to be determined in some way for each card read, at execution time (looking for spaces, looking for certain characters?). Similar problems had to be solved for lines to be printed: some fields were of varying length in memory but of fixed length on paper. Things that are simple in most computers were headaches in this one.
Surely these problems could have been helped by a high-level business-oriented language, however I doubt that one was ever made available. Would you like to write a COBOL compiler for this computer?
The 6001 was Olivetti’s answer to the IBM 1620, a transistorized scientific computer announced in October 1959. It did share some of the characteristics of the 1620. Its business version was an answer to the IBM 1401, good luck!
Olivetti Elea 9004, Elea 9104
The Elea 4001 was a 7-bit computer, on which the Olivetti engineering team worked around 1963. I gather from the information I have found that it was not marketed and evolved towards an 8-bit computer called Elea 4-115. In 1964 Olivetti sold its computer division to General Electric and this machine was adopted by GE, becoming the GE-115. It was also sold by Bull under the name Gamma 115. This one was a successful computer: apparently about 5,000 were sold worldwide. I have had no experience with these machines, but I have the 4001’s programmer’s reference card, which I am making available in case it interests anyone.
These are recollections from my working experience at Olivetti, Computer Marketing division, from 1961 to 1964. They are written mostly from memory, with the help of various sources. Corrections are welcome. Interventions could be included in the form of signed addenda after my text.
Much additional information can be found on the Web.
Marco, G.; Mainetto, G.; Pisani,
S.; Savino, P:
The early computers of Italy. Annals of the History of Computing, IEEE
Volume 21, Issue 4, Oct-Dec 1999 28 – 36
Parolini, G.: Olivetti Elea 9003: Between Scientific Research and Computer Business. IFIP, History of Computing and Education 3, 2008, 37-53.
Answer to quiz above: According to Wikipedia and other Web sources, the word software first appeared in print in a paper by statistician John W. Tukey in 1958 in the American Mathematical Monthly. Tukey is also credited with the invention of the word bit. However of course there are also differing stories on the web…