I have been working for a long time in a company where all ASSEMBLER
code was
using SP macros, and there were no compare instructions and no branches
in the code.
To make this possible, it is IMO necessary that you have in addition to
the SP macros
like IF, THEN, ELSE, EIF, LOOP, BREAK, ELOOP, LEAVE etc. a sort of
"lightweight" PCALL,
PROC end ENDPROC macro, which allows for inline procedures, so that you
are able to
call "structure blocks" of code and to build well structured large
programs.
The "lightweight" call macros should not do the full featured register
save conventions
as it is done for external module calls, but they should save some
registers (for example
regs 10 thru 14), and they should exstablish new base registers for a
static data area
which follows the code (static local variables). So each function block
can have its own local
static variables and constants and literal pool (don't forget LTORG).
Calls between those
function blocks have to be done using address constants, so that there
are no restrictions
regarding distance.
We had such macros in the company mentioned above, and I improved them
in the last
years to allow for "baseless coding" (meaning: the code part of the
function blocks is not
covered by base registers, all branches are relative branches - the SP
macros support this).
If you specify this global "baseless" parameter (specified at the
startup macro and controlling
all SP macros and the lightweight CALL and PROC macros), there is only
one base register
which covers the area after ENDPROC, allowing for up to 4 k of local
static variables
(this is the default, of course you can have more, but if your function
blocks are small
and you have many of them, your module size if virtually unlimited).
I cannot share these macros, but if you want me to write similar macros
for your company,
contact me offline.
to Frank specifically: PERFORM is CALL, and J is GOTO ...
PERFORM is ok (from Dijsktra's point of view), as it leaves the
structure of your program intact,
but J is not (see: "Goto Statement considered harmful"). The use of the
SP macros should lead
to programs that get rid of all branches.
Kind regards
Bernd
Am 17.05.2016 um 19:43 schrieb Swarbrick, Frank:
This is exactly true. That being said, I don't know how structured programming
macros can be used for 100% of your code if you want to also use the minimum
number of instructions possible. These two things appear to be in conflict.
For example, I did this simple code:
IF (TM,0(R6),UEPPSB1,O)
J PSBFUNC
ENDIF
Which generated this:
TM 0(R6),UEPPSB1
BRC 14,#@LB5
J PSBFUNC
+#@LB5 DC 0H
But without using the macros I'd simply do this:
TM 0(R6),UEPPSB1
JNO PSBFUNC
So it seems like there might be implied guidance to not use an IF macro if the
only conditional code is a branch. Or is there something I am missing? I know
there is DOEXIT, but that doesn't really fit in this case.
I should qualify that I know that I *could* do something like the following:
IF (TM,0(R6),UEPPSB1,O)
[lots of code here]
ELSE
[lots of code here]
ENDIF
I choose not to because I have a philosophy, for higher level languages anyway, that if "conditional
code" is more than a "few" lines it should be taken "out of line" and invoked. For
example, in COBOL, instead of
IF SOME-CONDITION
[50 lines of code goes here]
ELSE
[30 lines of code goes here]
ENDIF
I would do this:
IF SOME-CONDITION
PERFORM 50-LINES-OF-CODE
ELSE
PERFORM 30-LINES-OF-CODE
ENDIF
The compiler, of course, is free to bring the "performed" code inline. And, of
course, an assembler will not do that.
I have only been using the SP macros for a total of three days, so if I am
missing a possibility please let me know!
Frank