Month: August 2012

A Little Assembler MagicA Little Assembler Magic

In most languages, if you need to swap the contents of two variables, say X and Y, it normally requires a third temporary location:

 Temp = X;

 X = Y;

Y = Temp;

But in assembly language, if the two variables are stored in registers (or even in memory), you can swap them without using a third register (or variable).  Here’s the code that uses an exclusive or to swap the values:

XR    R5,R3

XR    R3,R5

XR    R5,R3

Try it yourself with some real values and you can almost see the bits exchanging places.  Presto, Changeo!  A little assembler magic. 

The Secret of PUTs and GETsThe Secret of PUTs and GETs

PUTs and GETs are easy, right? PUT FILEOUT,RECOUT adds the contents of RECOUT as a new record in FILEOUT. GET FILEIN,RECIN reads a record off FILEIN and stores it in RECIN. Simple, yes? But there is a little known fact about the PUT and GET macros that you might find interesting. It really doesn’t matter which macro you choose to code (PUT or GET) because both macros generate identical code. Hard to believe, but these macros are interchangeable. You can see this in the example below. Lines 90-94 were generated by a PUT macro and lines 97-01 were generated by a GET macro. See for yourself: Both macros generate the same code.
87 PRINT ON,NODATA,GEN
88 PUT FILEIN,RECORDIN
90+ LA 1,FILEIN
91+ LA 0,RECORDIN
92+ SLR 15,15
93+ ICM 15,7,49(1)
94+ BALR 14,15
95 GET FILEIN,RECORDIN
97+ LA 1,FILEIN
98+ LA 0,RECORDIN
99+ SLR 15,15
00+ ICM 15,7,49(1)
01+ BALR 14,15
02 PRINT ON,NODATA,NOGEN
So how does the machine distinguish when you want to read a record, and when you want to write a record if PUT and GET are equivalent? The answer lies in the OPEN macro which does all the heavy lifting. It’s in the OPEN macro that you indicate the type of operation you intend to invoke on the file: OPEN (PRINTER,(OUTPUT)) or OPEN (FILEIN,(INPUT)).
A little knowledge is sometimes a dangerous thing, so while PUT and GET may generate the same code, I don’t recommend coding PUT when you want to read a file, or GET when you want to write to one. That would be unnecessarily confusing to the programmers coming behind you. After all, one of those programmers is likely to be you.

Small is BeautifulSmall is Beautiful

The first computer I owned was an Apple II Plus.  It had a 6502 chip with an accumulator register and a couple of index registers.  From a programmer’s point of view, most of the work got done in the accumulator and half the machine cycles were spent doing loads and stores (load a value, add, store, …).  Essentially, it was a one register machine.  So when I started programming IBM mainframes, I was delighted to see that each machine came equipped with 16 general purpose registers.  Why so many?  Who needed so many registers?

As is often the case, I was wrong:

Register 0 – used occasionally to pass a parm

Register 1 – used for parameter passing

Register 2 – Available, but sometimes corrupted by TRT

Register 12 (And perhaps a few others) – Your typical base register

Register 13 – Points at a save area

Register 14 – Points to the return address

Register 15 – The target address for program calls and the return code register

So … what does that leave us?  Registers 2 through 11, or 3 through ?

Dive into many production programs and you’ll find that all the registers were allocated years ago.  Good luck finding a free register.  Many programs are so code-bloated that simply adding another variable will cause thousands of addressability errors.  What’s a programmer to do?

There are two strategies:

1)  Store the values in one or more registers.  Do the work you need to do.  Restore the registers to their previous values.  Ugly, but effective.

2)  Start a new program, pass it the data it needs, return the values you have computed.  The nice thing about this approach is that you start from a clean slate.  All the registers are yours to use as you see fit.

So … do we have enough registers or not?  It would be nice to have more, but I think 16 general purpose registers are sufficient.  Sometimes, constraints are a good thing – think Haiku.  In writing assembler programs, we need to think smaller and more modular.  Many maintenance assembler programmers use strategy 1 because it’s easier and they can turn the work out faster.  But in many cases, particularly for programs that have maxed out the storage covered by existing base registers, the second strategy may be the best choice. 

If you are writing something new, one base register should be sufficient.  If you find you need a second base register, it’s probably time to re-factor.  Small is beautiful