Skip to content
October 12, 2010 / gus3

Was Taken For Granted, Now Forgotten

I found a computing treasure in a local Goodwill store three weeks ago: a book about System/360 assembly language. (Assembly language is the human-readable form of the concrete instructions carried out by the computer.) In earlier years, this would have been a wonderful surprise, but a previous find precludes that from happening… Last year, I found a special treat in the discount bin of a local grocery store: a movie, in Mongolian. In the rural Midwest USA, that is difficult to surpass that for surprise finds.

Anyway, the System/360 project had a huge mandate from IBM: the design had to include software which would hide the differences among the different System/360 models. (That software became OS/360, from which experience Fred Brooks wrote the inestimable volume The Mythical Man-month.) The system was a success, despite numerous obstacles, and became so popular that today’s powerful System/390 will still run programs built on the original System/360.

This philosophy on programming by intentions, rather than to the hardware, gave rise to the compact and highly symbolic (hence immensely popular) C programming language, designed by the originators of the portable Unix operating system.

This book gives some real insight into the way computer programming used to be:

  1. Economy of temporary storage. A low-end System/360 had 8,192 bytes of online memory, for both the running program and its workspace. Temporary storage was precious, and a program using it showed its purpose clearly.
  2. Economy of long-term storage. In terms of computing time, accessing the disk or tape was a very expensive operation. Finding and retrieving the desired data could take several thousand to several million machine cycles. The book’s first example of long-term storage retrieval involves reading punched cards, while demonstrating how issuing the read operation well ahead of using the retrieved data allows the processing to be distributed over different components of the system.
  3. No stack. Almost all modern computers have some sort of LIFO storage instructions built-in, for storing data into a holding area in memory. Some, like Intel and Zilog, have it explicitly, while others, like Sparc, ARM and MIPS, have it by implicit convention. But this book shows no evidence that the System/360 had anything resembling a stack. Temporary data was managed by the program explicitly, and a subroutine’s return address was typically stored in a CPU register. If a subroutine called another subroutine, it had to store its own return address somewhere before the next subroutine used the same register for its own (return address) purposes. Other data, which might be over-written by the called subroutine, also had to be stored in memory, typically in a fixed location. This makes recursion impossible without designing it into the software.
  4. The humans worked harder. A programmer’s time cost less than a computer’s time, so the programmer was expected to put much more offline work into checking the program before its first online test. Interactive debugging was nearly impossible; code instrumentation was strongly discouraged, due to the extra memory it required.
  5. The expected installation base is obvious. Both addition and subtraction support several numeric formats: the usual binary, plus packed decimal and unpacked EBCDIC, in arbitrary widths. All numeric values could be negative. These are accompanied by a plethora of format conversion instructions, so that even a packed decimal can be turned into unpacked, printable characters, complete with a currency marker, comma grouping, and right-justified in a field. On the typical desktop computer, the processor would require several hundred instructions, and a few thousand machine cycles, to accomplish the same conversion. The System/360 needs just a few instructions, plus a “map” describing the intended printout. Clearly, it was made for business accounting and reporting.

So far, I have read the foundational chapters, plus chapters on program modules and subroutines, and one on debugging (including how to read a printed System/360 core dump!). I am now reading the chapter about assembly macros.

Some may deride such “old school” studies. My response is to remind them that great work comes from great challenges. The sonnet form gave William Shakespeare a framework for the greatest soliloquies in the English language. What would Georges Seurat‘s paintings be like without the slow, dot-by-dot technique? The first running version of Unix was on a PDP-11/20, the very first delivered PDP-11 model, very weak by today’s standards.

Only by looking at the past, can we truly appreciate the future.

Advertisements

8 Comments

Leave a Comment
  1. fstephens / Oct 12 2010 2:11 pm

    I learned to program in assembly on an IBM 360/30. Can’t remember a bit of it now…
    Wait, I do remember one instruction: “shift left logical” I think.

  2. JPP / Oct 12 2010 8:20 pm

    Assembly language did not execute directly in hardware. It was emulated in a micro-program. That way all OS-360 models looked functionally equivalent even though the hardware was vastly different from model to model.

  3. David Smith / Oct 13 2010 12:55 am

    God, did your post take me back. I once worked as an application programmer in long-ago defunct Security Pacific National Bank. I learned Assembler for the System 360. I actually enjoyed learning what little I did, and using it. The idea of being able to exert such close control over the machine appealed to me.

  4. Frank Bernhardt / Oct 13 2010 10:26 am

    Wow! Was it the green book? I threw mine away a couple of decades ago although I still have and use my 370 reference card (the green 360 one fell apart long ago).
    I can still remember dreaming about wading through core dumps and it really was core; tiny round ferrite rings with wires threaded through the middle. If I remember correctly 2 to magnetize and 1 to read the corresponding 1 or 0.
    Thanks for posting this, it was a nice BALR from work.;-)
    Cheers.

  5. gus3 / Oct 13 2010 9:51 pm

    JPP: By “intentions, not hardware,” I meant that, instead of writing a program for the System/360-30, and then adjusting it to run on the System/360-40, one could send requests to the OS/360 running on that particular platform, and let it handle the differences between the System/360 models. The actions that most programs might want to do, were made available in the OS for general use, and the OS took care of the particulars.
    David and Frank: Glad you enjoyed the trip down memory lane! I do assembler programming occasionally on x86-64, but started out on the Z-80. It’s kind of funny to think how register-starved the original x86 and Zilog lines were, after seeing how rich the older S/360 was by comparison. Of course, also by comparison, the S/360 was starved for core…
    Oh, and the book is a dark purple view of desert dunes. I don’t know if it’s a really good night shot, or if it was adjusted to purple in the photo lab.

  6. Stephane / Oct 15 2010 10:03 pm

    The DEC ALPHA architecture doesn’t define an hardware stack.
    The Branch or Jump instructions can save the PC in another register, it’s programmer’s responsibility to save it somewhere in memory.

  7. gus3 / Oct 15 2010 11:00 pm

    @Stephane, you are correct. I would group the Alpha with the Sparc, ARM and MIPS as having a stack “by implicit convention.” There isn’t an explicit stack defined by the instruction set, but the calling conventions of the running OS can dictate a particular register as the stack pointer, so that allocation faults involving the stack can be handled correctly. Using a different register for “decrement-and-store” would confuse the fault handler, resulting in an unhandled access exception.
    Following that convention, another implicit convention specifies a register to hold a subroutine’s return address. If that subroutine isn’t a “leaf function” (i.e. it calls another subroutine), it can save the return address on the stack before making the call. After the call returns, the old return address is retrieved from the stack.
    OTOH, Intel and Zilog have hard-coded stack pointers, with instructions dedicated to them. PUSH, POP, JSR/CALL and RET are such instructions, among others. Following Intel’s ModR/M charts, the stack pointer is binary 100 in the register file. On the Z-80, several 16-bit instructions use binary 11 to specify the stack pointer, even if the SP-based instructions are documented separately (e.g. INC BC, opcode 03h vs. INC SP, opcode 33h).
    The Motorola 68K is an interesting hybrid. The stack pointer is clearly documented as A7 (address register 7). Some instructions (like BSR, branch to subroutine) contain no register file offset to A7 within the opcode. Other instructions (like “MOVE.L -(A7),D3”, which pushes D3 onto the user stack) clearly contain a reference to register 7 within the opcode.
    Yes, I’ve studied this stuff entirely too much. Why else would I get such a kick from a System/360 assembly language book?

  8. gus3 / Oct 19 2010 9:42 pm

    As a follow-on to comment #7:
    The difference between a true stack, and the user manually programming decrement-and-store, load-and-increment, is in the number of instructions used for the operation. The example I use is “MOVE.L -(A7),D3”, which accomplishes the decrement-and-store in a single instruction. On processors supporting it, a stack can provide tremendous flexibility in program development.
    The System/360 does have a per-process area called the “register save area,” which holds the process state while some other process is running. The macro instruction “SAVE (14,12)” will save all the user registers to that area, except R13, which is used by OS/360 to point to the register save area. This may be accomplished within the CPU using stack-based methods, but the book mentioned no such instructions available to the programmer.
    However, digging through the System/390 architecture section of the Linux source code, it’s obvious Linux uses R15 as a stack pointer. This is specific to Linux on the S/390; see this PDF for an assembly language compare/contrast between Linux and z/OS.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: