Is there (was there ever?) serious programming being done in machine code?

Quite so. An interesting sidelight to this is that Gordon Bell regarded the PDP-11 range as comparing favourably to what IBM had achieved with the System/360, mentioning in that paper you cited that there was about a factor of 500 between price and memory size of the smallest and largest models. The PDP-11 actually had some interesting commonalities with System/360: a byte-oriented architecture, a set of general-purpose registers, a Program Status Word (PSW) holding condition codes, and the use of microprogramming to create systems across a wide cost and performance range. I believe every PDP-11 except the original Model 20 was microcoded, but with radically different performance tradeoffs.

Oh, I’ve been reading along, and with interest; it’s been really enlightening to read people’s views, even though I must admit the discussion has long exceeded my level of expertise. It’s been particularly interesting to hear from people who have been in IT for a very long time and still have first-hand experience with technology from the old days.

As far as I’m concerned, my takeaway from this is threefold:

  1. Programming in assembly does take place;
  2. There’s room for debate to what extent it is fair to claim that “programming in assembly” is synonymous with “programming in machine code”;
  3. If one wants to draw a distinction between the two, then “programming in machine code” takes place only in very limited niches.

But that doesn’t claim to be a comprehensive synthesis of the debate, only an overview response to what I was having in mind when I asked.

It’s called a geezer fight.

For reference

I have great love and respect for my fellow geezers.

“We only had zeros and ones, and sometimes we didn’t have ones”

Brian

You jest, but in my capacity as an official Old Geezer, speaking only from personal experience, I will say that there’s a good reason we Geezers like to reminisce about these things. I’ve had some great jobs in my career, including working for DEC for many years, which was without a doubt the best “serious” job I’ve ever had. But to be perfectly honest, the absolute best most pure fun I’ve ever had was in my younger years preceding that, working at a university research lab. Those were the days when I lived and breathed the PDP-10, PDP-8, PDP-11, and PDP-12. It was pure joy, the kind that only comes with youth and living in a fairy-tale world. And that’s why I’ll never forget those systems. They were an integral part of one of the best periods of my life. With the advent of VAX/VMS I started down a serious career path, eventually ending up at DEC, but some of the pure joy was beginning to evaporate due to the demands of the real world of business. :slight_smile:

A long time ago in the 80’s, I worked with a chap who had the Z80 instruction set memorized well enough that he could knock out short programs directly in hex. Of course for any serious larger work he used an assembler program like the rest of us. I guess way back in the early days of computing this was the only way to get a program written for a new machine, until you had bootstrapped enough code to make an assembler program. Nowadays one would obviously use a cross-assembler on some existing machine to generate the target code. And yes, I do remember toggling in a dozen or so instruction words on the front panel of a PDP11 to enter a rudimentary paper tape reader program to get things started! Rather nostalgic: times when a single engineer could actually have a full understanding of the hardware AND software of a machine…

IBM was a leader in microprogramming. I got interested in it when I read a paper by an IBM engineer about it, and I got to sit at the same table with him at Micro8 which was cool.
Besides what you said, an advantage of them microprogramming the 360 was they were able to emulate the instruction sets of some of their computers with a large installed base, so someone owning one could move the (machine) code over, not have to recode, and run much faster.
This was crucial.
I think the very high end 360s might have been directly implemented in hardware, but definitely not the lower end ones.

It occurs to me that I used to have a hex editor somewhere handy on my hard drive.

That’s not the case now. I know I have one (probably more) somewhere on my computer, but I haven’t used one for a long time, and haven’t used one to edit code for much longer.

You and I have different memories of the PDP days. :wink:

Cryptic commands, numbered directories, yeah, joy isn’t a word that I would use to describe it. I really preferred the VAX.

FWIW, I still have a PDP-11 sitting in my garage. It doesn’t work, and hasn’t worked in 20 years. It’s really just taking up space. I don’t know why I haven’t bothered to get rid of it.

I still have one, and last used it a couple of weeks ago.

To be clear, the “joy” I refer to was not so much related to actually programming these beasts, but to the nature of my job, and the magical zeitgeist of the campus computing community at the time. We also had a close working relationship with DEC, as a result of which I had many pleasant visits down to meet with DEC engineering folks, being shuttled around between facilities in DEC’s own fleet of helicopters. I was just a kid at the time and it was the whole package that was a joy, but yes, I do have very fond associations with the machines themselves.

As for the disdain for “numbered directories”, I don’t think this is entirely fair. This was a well-reasoned practice that originated from the PDP-10 (actually, I think from its predecessor, the PDP-6). It arose from the fact that each user account had two distinct parts, a project number, and a so-called programmer number, collectively called the PPN. The PPN was used to log in to the system, and the two fields were used for both billing and security purposes. For instance the PPN allowed a user directory to be (1) accessible globally, or (2) accessible only to project members, or (3) accessible only to the individual user. So it made sense for the directory itself to have the same name as the PPN. [1,1] was a special system directory that contained the file structure’s Master File Directory. [1,2] was a special operator PPN that had all system privileges (and so the one that our resident campus hackers were always trying to break into!).

A similar idea was later implemented on other systems, notably the RSX-11 family on the PDP-11, and in some systems later evolved to a symbolic user name mapping.

Also, be fair: “cryptic commands” are really in the nature of any command-line interface. DEC’s PDP commands were actually relatively clear and straightforward compared to many others, like UNIX. If you want an example of really cryptic, consider the System/360’s JCL!

Not true. Assemblers output machine code, but can be written in anything. I’ve written one in Basic a long time ago. They’re actually pretty easy to create for most processor families.

I think what Hari means is that, absent the availability of some other machine, on a brand-new machine design with no other software you’d have to bootstrap the process of writing the first assembler by writing a very simple one in machine code and then using that to gradually increase its capabilities. This is correct, though as he says, I don’t imagine anything like this has needed to be done for a very long time, since there’s always some other machine you can write a cross-assembler on.

I would argue, though, that this has nothing to do with simulators. A cross-assembler is simply an assembly program running on one computer that produces object code for a different computer. One that was commonly used at DEC for large programming projects was a PDP-8 cross-assembler running on the PDP-10, because the PDP-10 was a large, sophisticated timesharing mainframe and the cross-assembler was more capable and easier to use than anything that could run natively on the PDP-8. It was called PAL10: “PDP-8 Assembly Language for the PDP-10”. The famous FOCAL interpreter for the PDP-8 was written on the PAL10 platform.

Old joke: Q: How do you tell that the guy broken down on the highway is a DEC repairman?

A: He’s swapping tires.

I always heard it as:

How does a DEC repairman fix a flat tire?

He swaps the tires out one at a time until he finds the flat one.

What does a DEC repairman do when he runs out of gas?

He swaps the tires out one at a time until he finds the flat one.

Of course, that was in the RISC and Alpha era, and they wanted to be called “Digital” then.

Q. How long does it take a DEC repairman to change a flat tire?
A. It depends upon how many flat tires he has brought with him.

These jokes go back way before the era of MIPS and Alpha.

I once programmed a short program (a loop counting) into a PDP6 using the front switches just to see how it worked.

I have a copy of the original Radio Electronics “Build this Microcomputer” plans featuring a 8008 and a design for an add-on 256-byte memory expansion board. I found it in our Systems Programmer’s papers after he left.

I still have my dad’s Curta mechanical calculator from the late 1950’s - a miracle of mechanical engineering.

My dad told me about programming some old computer from the early early days in his lab. In the days before RAM memory and when core was expensive, this thing had a giant magnetic drum for memory. As it spun, a row of heads read (and wrote) tracks on the drum to get the memory contents. You programmed it using a spreadsheet - real spreadsheet, a double-size piece of paper preprinted with blocks representing the cells on the drum. You filled these in with the opcodes and operand addresses. Each instruction also had data at the end indicating the cell address of the next instruction. Part of the challenge was, as you planned each instruction, to determine how many clock cycles that operation would take and therefore how far around the drum - which cell - to locate the next instruction to avoid having the computer wait long times on drum latency. He never did say how the drum data was entered but I assume something like punch cards or a manual process.

He also got the PDP6 in the 70’s for his lab. Later he bought a 286 computer. (Still had it in the basement when I went to help clean out the house). He mentioned that he’d transferred some mainframe FORTRAN programs to a PC compiler; he did things like diagonalizing a 50x50 matrix, which would run for 48 hours or more. When he bought a 486 he tried the program, then spent half an hour trying to debug it before he realized it hadn’t crashed - it had finished in 5 minutes while he was making coffee. (He never did cotton to that newfangled Windows malarkey and only used it reluctantly).

Floating point before the 387 math coprocessor and 486DX was done using binary arithmetic, byte by bye, in subroutines. I recall an ad for “turn your 386 into a 486” for gamers - basically it replaced the floating math subroutines with ones that only did 3 or 4 significant digits, since for most games with screen resolution 1024x768 3 digits was sufficient and ran significantly faster.

An assembler program where all the labels are AAA, BBB, etc was obviously run through a disassembler, either written in machine language originally, or they lost the source code The bits that jump to near the end of the program likely indicate where patches, fixes, and addenda were added; and with a lack of coherent modular writing, it made more sense to simply tack these routines on the end.

My very minor exposure to IBM 360/370 assembler IIRC indicates a business machine constructed for COBOL; many of the COBOL instructions would have direct machine language equivalents - ADD this memory location with this binary coded decimal number of this length with this many decimal digits to this location with (other custom BCD number specification) and store in this location with (other custom BCD number specification); It was an adjustment to think in byte and word binary arithmetic instead.

The 8087 math co-processor was a thing. The original IBM PC even came with a socket for it, allowing you to install one yourself. Later, the IBM PC-AT also came with a socket for the 80287.

Back in the day I wrote a program in Turbo Pascal to generate Mandelbrot set images. This was on PC clone with a NEC V20 but without a math co-processor. Since the set is bounded by ±2, I optimized the central calculation to use integer instructions to do fixed-point arithmetic with the first two bits being to the left of the decimal point. The early version of Turbo Pascal I was using at the time couldn’t link external object code, not that I had access to an assembler anyway. It could run inline machine code however. So I wrote the integer math routine in assembler, hand assembled it into hex opcodes, and fed that into the compiler. Ran perfectly right off the bat.

The first commercial computer, the IBM 650, worked that way. However, the programmer didn’t have to worry about figuring out the optimal instruction placement – that work was done by the assembler. The assembler was called SOAP, for Symbolic Optimizing Assembly Program. “Symbolic” because you used mnemonic symbols for instructions and symbols for memory addresses, and “optimizing” because the assembler did the grunt work of figuring out the optimal instruction placement on the drum. And yes, part of each instruction was the drum location of the next one.

The 650 was a vacuum tube computer and the drum was its main memory, although you could optionally get a very limited amount of core memory for it. The main input method was punched cards.

The LGP21 had no RAM, but memory was on a drum/disk. The manual I linked to had what address to use next to reduce latency between subsequent memory reads and writes.

The 486SX, interestingly enough, was a 486DX where the floating point unit was either disabled because it was faulty or because the market wanted more cheaper devices.
The SPARC Niagara processor was sold in a version with fewer than the max number of CPUs. Some were from one or two being bad, and selling the reduced power version increased effective yield, but in some all the processors were good but a few were turned off to be sold at a lower price point.

Yield management and deliberate feature disabling is still common. After testing, CPUs and GPUs are sorted into various categories (all cores working at max specification, all cores working at reduced specification, some cores working at max specification, some cores working at reduced specification). All of those chips are sold as various models/price points. As production line yields improve, more production falls into the higher specification categories, but the actual demand in the market is less elastic. To maintain market banding, rather than drop the cost of higher spec devices, often full specification devices are under-clocked or have cpus disabled to meet demand in a lower price band. This underclocking/disabling can be soft (which may be able to be reversed, allowing overclockers to purchase low-cost devices and boost them) or hard - usually a fusible link that can be blown with an electrical pulse or laser. I remember that some older AMD CPUs could also be modified by linking metal pads on the chip surface with conductive ink to allow overclocking/core enabling.