Assembler Language Macro "Boot Camp" Part 2
Macro Boot Camp Part 2.pdf - Kcats.org
Macro Boot Camp Part 2.pdf - Kcats.org
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Assembler</strong> <strong>Language</strong><br />
<strong>Macro</strong> "<strong>Boot</strong> Camp"<br />
<strong>Part</strong> 2<br />
SHARE in Austin<br />
March 1 - 6, 2009<br />
Session 8159<br />
Who am I?<br />
Michael Stack, K Cats Consulting<br />
Instructor in Computer Science at Northern<br />
Illinois University from 1982 - 2007, including<br />
assembler language, data structures (in<br />
assembler), and applied systems programming<br />
Available Materials<br />
Materials described in these two sessions,<br />
as well as the <strong>Assembler</strong> <strong>Boot</strong> Camp, can be<br />
found at http://www.kcats.org/share<br />
Yesterday's Agenda (Brief Review)<br />
Our First <strong>Macro</strong> Instruction<br />
The Second Version of Our ADD <strong>Macro</strong><br />
The <strong>Macro</strong> Programming <strong>Language</strong><br />
1-4
Today's Agenda<br />
Variable Symbols We Can Change<br />
A Bit More on Variable Symbols<br />
Finally, the Add <strong>Macro</strong> Instruction<br />
Wrap Up<br />
Variable Symbols<br />
We Can Change<br />
(So that's why they're called<br />
Set Symbols)<br />
Set Symbols<br />
Now that we have AIf and AGo to control<br />
the path of code generation, it will be very<br />
useful to have a way to keep assembly-time<br />
data<br />
<strong>Assembler</strong> variables which can hold this<br />
data are called set symbols, of which there<br />
are three data types<br />
Arithmetic<br />
Binary (logical)<br />
Character<br />
Set Symbol Scope<br />
As with high level languages, set symbol<br />
variables have the scope characteristic<br />
The value assigned to a local set symbol is<br />
known only within one macro expansion,<br />
and each expansion of that - or any other -<br />
macro has its own copy of that local variable<br />
The value assigned to a global set symbol is<br />
known throughout the assembly<br />
5-8
Set Symbol Declaration<br />
Modern assemblers do not require that local<br />
Set Symbols be declared before use (older<br />
assemblers do, though)<br />
But it's a good idea to declare (and globals<br />
require it), as it's a great place to document<br />
the purpose of the variable<br />
Declaration describes the variable as<br />
Local or Global<br />
Arithmetic, Binary, or Character<br />
Set Symbol Declaration<br />
To declare a local set symbol of type x<br />
(where x is A, B, or C):<br />
seq_sym Lclx var_sym 1 ,var_sym 2 ,...<br />
where seq_sym may be a sequence symbol<br />
and each var_sym n is a variable symbol<br />
To declare a global set symbol of type x:<br />
seq_sym Gblx var_sym 1 ,var_sym 2 ,...<br />
Although more than one set symbol can be<br />
declared in one statement, limiting to one<br />
leaves room for a descriptive comment<br />
Arithmetic Set Symbol Assignment<br />
The SetA instruction is used to assign a<br />
value to an arithmetic set symbol (from now<br />
on called a SetA symbol)<br />
var_sym SetA arithmetic_expression<br />
var_sym is a variable symbol and<br />
arithmetic_expression (as described earlier)<br />
is evaluated as a signed, 32-bit number<br />
The default (initial) value of a SetA symbol<br />
is zero<br />
Arithmetic Set Symbol Assignment<br />
Example<br />
Here is some sample code:<br />
LclA &S Counter<br />
LclA &Con Assigned "constant"<br />
&S SetA 3 Initial value<br />
&S SetA &S+1 Increment by 1<br />
&Con SetA 2*(1-&S) Set &Con to -6<br />
And here's a real oddity: when &Con<br />
(whose value now is -6) is used in a model<br />
statement, its absolute value is used:<br />
DC F'&Con' Generates 00000006<br />
(Don't ask)<br />
9-12
Arithmetic Set Symbol Assignment<br />
Example<br />
Here is some more sample code, this one to<br />
generate all of the register equates:<br />
<strong>Macro</strong><br />
EQURegs<br />
GblA &EQURegs Recall if already done<br />
LclA &Reg Counter (initially 0)<br />
AIf (&EQURegs NE 0).Done<br />
&EQURegs SetA 1 Don't generate again<br />
.Loop ANOP<br />
R&Reg EQU &Reg<br />
&Reg SetA &Reg+1 Increment reg number<br />
AIf (&Reg LE 15).Loop<br />
.Done MEnd<br />
Arithmetic Set Symbol Assignment<br />
Example<br />
Here is the output (assembler source) from<br />
EQURegs (first time only!)<br />
EQURegs<br />
+R0 EQU 0<br />
+R1 EQU 1<br />
+R2 EQU 2<br />
+R3 EQU 3<br />
+R4 EQU 4<br />
...<br />
+R12 EQU 12<br />
+R13 EQU 13<br />
+R14 EQU 14<br />
+R15 EQU 15<br />
Arithmetic Set Symbol Assignment<br />
Example<br />
Here is a slightly different version of the<br />
same macro (loop test at top):<br />
<strong>Macro</strong><br />
EQURegs<br />
GblA &EQURegs Recall if already done<br />
LclA &Reg Counter (initially 0)<br />
AIf (&EQURegs NE 0).Done<br />
&EQURegs SetA 1 Don't generate again<br />
.Loop AIf (&Reg GT 15).Done<br />
R&Reg EQU &Reg<br />
&Reg SetA &Reg+1 Increment reg number<br />
AGo .Loop<br />
.Done MEnd<br />
Binary (Logical) Set Symbol<br />
Assignment<br />
The SetB instruction is used to assign a<br />
value to a binary set symbol (from now on<br />
called a SetB symbol)<br />
var_sym SetB binary_value<br />
var_sym is a variable symbol and<br />
binary_value (described in the next slide) is<br />
evaluated as a 0 or 1<br />
The default (initial) value of a SetB symbol is<br />
zero<br />
13-16
Binary (Logical) Set Symbol<br />
Assignment<br />
A full description of the binary_value<br />
operand of SetB is beyond the scope of<br />
these sessions; simplified, it can be one of<br />
A binary digit (0 or 1)<br />
A binary value enclosed in parentheses<br />
An arithmetic value enclosed in parentheses<br />
If the value is 0, the assembler assigns a<br />
value of 0 to the symbol in the name field; if<br />
the value is not 0, the assembler assigns a<br />
value of 1<br />
A logical expression enclosed in parentheses<br />
Binary (Logical) Set Symbol<br />
Assignment Examples<br />
Each &X starts with initial &A, &B, & &C<br />
&A SetA 4<br />
&B SetB 1 (Note no parentheses)<br />
&C SetC 'XYZ' (This is a preview of SetC!)<br />
*<br />
&X SetB (&B) &X = ?<br />
&X SetB (NOT &B) &X = ?<br />
&X SetB (&A LE 15) &X = ?<br />
&X SetB ('&C' EQ 'XYZ') &X = ?<br />
&X SetB ((NOT &B) AND (&A LT 15)) &X = ?<br />
&X SetB ((&A GT 0) AND (&A LT 15)) &X = ?<br />
&X SetB (&B OR ('&C' EQ 'YES')) &X = ?<br />
&X SetB (&B AND NOT (&A GT 5)) &X = ?<br />
Character Set Symbol<br />
Assignment<br />
The SetC instruction is used to assign a<br />
value to a character set symbol (from now<br />
on called a SetC symbol)<br />
var_sym SetC 'character_string' note quotes!<br />
character_string is a sequence of characters<br />
and variable symbols (followed by '.' for<br />
concatenation) interpreted as characters<br />
The initial value of a SetC symbol is the null<br />
string<br />
Character Set Symbol<br />
Assignment Examples<br />
Here is a SetC example:<br />
&A SetA 4<br />
&B SetB 1<br />
&C SetC 'XYZ'<br />
*<br />
&X SetC 'A&A.B&B.C&C.' &X = ?<br />
&X evaluates to the string A4B1CXYZ<br />
Note that the arithmetic and binary values<br />
have been converted to character values<br />
(See Concatenation in the next section)<br />
17-20
Substrings of SetC Symbols<br />
Definition<br />
SetC operands can also be substrings by<br />
placing two arithmetic expressions,<br />
separated by commas and enclosed in<br />
parentheses, immediately following the<br />
character expression<br />
The first arithmetic expression identifies the<br />
first character of the substring<br />
The second arithmetic expression gives the<br />
length of the substring<br />
Substrings of SetC Symbols<br />
Examples<br />
'ABCDEF'(3,2) evaluates to 'CD'<br />
If &VAR evaluates to 2 and &STR evaluates<br />
to 'ABCD' then '&STR.%'(2,&VAR*2)<br />
evaluates to 'BCD%'<br />
'AB'.'CD'.'EFG'(1,2).'H' evaluates<br />
to 'ABCDEFH'<br />
(For . see concatenation in the next section)<br />
Meeting<br />
in<br />
Progress<br />
A Bit More on<br />
Variable Symbols<br />
Then we can really go to work!<br />
Concatenation<br />
Concatenation can sometimes be without<br />
ambiguity<br />
&this&that (variable.variable)<br />
this&that (ordinary.variable)<br />
Others are a problem<br />
&thisthat (variable.ordinary intended)<br />
We use the concatenation operator '.' to<br />
avoid the ambiguity<br />
&this.that<br />
21-24
Symbolic Parameter Sublists<br />
A single macro operand can be a list of<br />
elements, called a sublist, with one or more<br />
items enclosed in parentheses and<br />
separated by commas<br />
(X,2,Y)<br />
An individual sublist item can be referred to<br />
by a subscripted symbolic parameter, so if<br />
&ABC has the value (W,15)<br />
&ABC(1) has the value W<br />
&ABC(2) has the value 15<br />
But &ABC.(1) has the value (W,15)(1)<br />
Keyword Symbolic Parameters<br />
<strong>Macro</strong> prototype statements may have<br />
keyword operands as well as positional<br />
These are coded on the prototype as<br />
&Keyword=[default]<br />
The default value is optional<br />
The advantages of keyword parameters are<br />
They can have a default value<br />
They can be coded in any order when invoked<br />
But positionals look more like operands<br />
System Variable Symbols<br />
The third kind of variable symbol after<br />
symbolic parameters and set symbols is the<br />
set of system variable symbols<br />
These all begin with &SYS so this prefix<br />
should be avoided in programmer-created<br />
variable symbols<br />
Some popular examples<br />
&SYSTIME - time of the assembly<br />
&SYSDATC - Y2K-compliant date of assembly<br />
&SYSNDX - (see the following slides)<br />
System Variable Symbol &SYSNDX<br />
Here is a macro - what's its problem?<br />
<strong>Macro</strong><br />
&name AddVal &num,&val<br />
.*<br />
.* <strong>Macro</strong> to add &val to &num<br />
.*<br />
L 0,&num<br />
A 0,FWrd<br />
ST 0,&num<br />
B FWrd+4<br />
FWrd DC F'&val'<br />
MEnd<br />
25-28
System Variable Symbol &SYSNDX<br />
The way it's written, it can be used only<br />
once in an assembly (because of FWrd)<br />
We can fix this by concatenating &SYSNDX<br />
&SYSNDX has a new value assigned by the<br />
assembler each time a macro is called<br />
For the first macro, &SYSNDX is 0001<br />
It increases by 1 for any macro invocation<br />
Until it goes past 9999, it is four characters<br />
This can provide unique labels for macros<br />
System Variable Symbol &SYSNDX<br />
Here is the macro rewritten using &SYSNDX<br />
<strong>Macro</strong><br />
&name Add1 &num,&val<br />
.*<br />
.* <strong>Macro</strong> to add &val to &num<br />
.*<br />
L 0,&num<br />
A 0,FWrd&SYSNDX<br />
ST 0,&num<br />
B FWrd&SYSNDX+4<br />
FWrd&SYSNDX DC F'&val'<br />
MEnd<br />
Attributes of Symbols<br />
As should be expected in a HLL (!) like<br />
assembler, symbols have attributes<br />
We will be concerned with only three<br />
Type, which distinguishes one form of named<br />
object from another, such as character data<br />
from binary data<br />
Count, which gives the number of characters<br />
required to represent the data as a character<br />
string<br />
Number, which gives the number of sublist<br />
entries in a macro instruction operand<br />
Attributes of Symbols<br />
We can refer to these attributes inside<br />
macro instructions by using a single letter<br />
followed by a single quote: T' K' and N'<br />
For example in the Add1 macro<br />
T'FWrd&SYSNDX is F<br />
And if we invoke as Add1 F4,18 then<br />
K'&num is 2<br />
N'&num is 1<br />
We will see more in the next slides<br />
29-32
Finally, The Add<br />
<strong>Macro</strong> Instruction<br />
In which we analyze and<br />
demonstrate an overloaded Add<br />
Add <strong>Macro</strong> Definition:<br />
Prototype and Doc Box 1<br />
<strong>Macro</strong><br />
&Name Add &List,&Sum,&R=1,&WKR=0<br />
.********************************************************************<br />
.*<br />
.* Function:<br />
.* This macro generates assembler instructions to add multiple<br />
.* values held in storage as fullword, halfword, and packed data.<br />
.* The first operand is a sublist of the labels on the numbers<br />
.* to be added. The sum will be returned in register R= as a<br />
.* binary value. Optionally, the sum may be returned in storage<br />
.* at the location given by the second operand, which must be of<br />
.* the fullword, halfword, or packed data type. Instructions<br />
.* will be generated appropriate to the data types.<br />
.*<br />
.* Prototype Statement:<br />
.* &Name Add &List,&Sum,&R=1,&WKR=0<br />
.*<br />
Add <strong>Macro</strong> Definition:<br />
Prototype and Doc Box 2<br />
.*<br />
.* Symbolic Parameters:<br />
.* &List is a sublist of the values to be added, consisting of<br />
.* labels of storage areas of types F, H, and P (required)<br />
.* &Sum is a label of type F, H or P and is the calculated sum<br />
.* (optional)<br />
.* &R= is the sum accumulation register; it is required and<br />
.* must be different from &WKR=; &R always has the result<br />
.* &WKR= is a scratch register for CVB and CVD instructions in<br />
.* case the sum or any summand is type P (required if any<br />
.* binarydecimal conversion is necessary)<br />
.*<br />
.* Error Conditions:<br />
.* Missing summand sublist (8)<br />
.* Incorrect sum or summand type (4)<br />
.*<br />
Add <strong>Macro</strong> Definition:<br />
Prototype and Doc Box 3<br />
.*<br />
.* Notes:<br />
.* Two registers are altered and not saved. By default these<br />
.* are R0 and R1.<br />
.*<br />
.* This exercise and solution are patterned after the ADD macro<br />
.* in _<strong>Assembler</strong> <strong>Language</strong> Programming for the IBM 370, ASSIST<br />
.* Edition_, by Frank M. Carrano, p. 18.34<br />
.*<br />
.********************************************************************<br />
.*<br />
33-36
Add <strong>Macro</strong> Definition:<br />
Set Symbol Declaration & Init<br />
.*<br />
.* Define and initialize local set symbols<br />
.*<br />
LclA &J &List loop counter<br />
LclB &P 1 if decimal summand seen, else 0<br />
LclC &A Current binary operation (L or A)<br />
LclC &DEC Current decimal op (ZAP or AP)<br />
LclC &H 'H' if LH or AH, '' if L or A<br />
LclC &D Unique label for work area<br />
LclC &NM &Name for flexibility in use<br />
.*<br />
&J SetA 1 Start with first summand<br />
&P SetB 0 No decimal summands yet<br />
&A SetC 'L' First time use L, then A<br />
&DEC SetC 'ZAP' First time use ZAP, then AP<br />
&H SetC '' Set to 'H' if binary is halfword<br />
&D SetC 'DWrd&SYSNDX' Unique label for D work area<br />
&NM SetC '&Name' &NM can be cleared, &Name cannot<br />
.*<br />
Add <strong>Macro</strong> Definition:<br />
Initial Check, Main Loop<br />
.*<br />
.* Sublist &List is required - quit if not present, CC=8<br />
.*<br />
AIf (K'&List NE 0).Loop<br />
MNote 8,'** Error: Required list of summands missing ***'<br />
MExit ,<br />
.*<br />
.* Begin loop to process summands<br />
.*<br />
.Loop AIf (T'&List(&J) EQ 'P').Decimal<br />
AIf (T'&List(&J) EQ 'F').FullBin<br />
AIf (T'&List(&J) EQ 'H').HalfBin<br />
MNote 4,'** Warning: Invalid summand type - &List(&J) **'<br />
&J SetA &J+1 Increment loop counter<br />
AIf (&J LE N'&List).Loop Continue if more summands<br />
AGo .EndList Else done with list<br />
.*<br />
Add <strong>Macro</strong> Definition:<br />
Process Binary and Decimal<br />
.*<br />
.* Process binary load or add, either halfword or fullword<br />
.*<br />
.HalfBin ANOP ,<br />
&H SetC 'H'<br />
.FullBin ANOP ,<br />
&NM &A&H &R,&List(&J) Increment binary part of sum<br />
&A SetC 'A' Use A after first L<br />
&H SetC '' and set fullword default<br />
AGO .LoopEnd Continue<br />
.*<br />
.* Process decimal zero and add, or add<br />
.*<br />
.Decimal ANOP ,<br />
&NM &DEC &D,&List(&J) Increment decimal part of sum<br />
&DEC SetC 'AP' Use AP after first ZAP<br />
&P SetB 1 We have seen a decimal summand<br />
.*<br />
.LoopEnd ANOP ,<br />
Add <strong>Macro</strong> Definition:<br />
Add Dec Summand, Dec Result<br />
.*<br />
.* Bottom of loop - check if any more summands<br />
.*<br />
&J SetA &J+1 Increment loop counter<br />
&NM SetC '' Clear &NAME holder after first use<br />
AIf (&J LE N'&List).Loop Continue if more summands<br />
.*<br />
.* All summands processed - if any were dec, get binary of their sum<br />
.*<br />
.EndList AIf (NOT &P).NoDSum Skip if no decimal summand<br />
CVB &WKR,&D Get binary sum of decimal summands<br />
&A.R &R,&WKR Add to sum of binary summands<br />
.*<br />
.* If the result is to be decimal, convert result to dec, then save<br />
.*<br />
.NoDSum AIf (T'&Sum EQ 'O').CKD If omitted, don't save result<br />
AIf (T'&Sum NE 'P').NoDRes Skip if no decimal result<br />
CVD &R,&D Get decimal sum of summands<br />
ZAP &Sum,&D Copy to target<br />
AGO .CKD Go generate DWORD<br />
37-40
Add <strong>Macro</strong> Definition:<br />
Store Result, Gen Temp Storage<br />
.*<br />
.* If the result is to be binary, save as halfword or fullword<br />
.*<br />
.NoDRes AIf (T'&Sum EQ 'F').SaveSum<br />
AIf (T'&Sum EQ 'H').HalfSum<br />
MNOTE 4,'** Warning: Invalid sum type - &Sum **'<br />
AGO .CKD Bad type, don't save sum<br />
.HalfSum ANOP ,<br />
&H SetC 'H'<br />
.SaveSum ST&H &R,&Sum Save result<br />
.*<br />
.* If any decimal summands or result, generate scratch doubleword<br />
.*<br />
.CKD AIf (T'&Sum NE 'P' AND NOT &P).MEnd<br />
B &D+8 Branch around doubleword<br />
&D DS D Scratch area<br />
.*<br />
.MEnd MEnd<br />
Add <strong>Macro</strong> Output:<br />
Example 1<br />
This is similar to the code in ADD2, except<br />
that this uses the RX add instead of RR (A<br />
instead of AR)<br />
*<br />
Add (Word1,Word2),Word3<br />
+ L 1,Word1 Increment binary part of sum<br />
+ A 1,Word2 Increment binary part of sum<br />
+ ST 1,Word3 Save result<br />
...<br />
*<br />
Word1 DC F'4'<br />
Word2 DC F'6'<br />
Word3 DS F<br />
*<br />
Add <strong>Macro</strong> Output:<br />
Example 2<br />
AddDemo Add (One,Two,Three,Two,Three,One),Three<br />
+AddDemo L 1,One Increment binary part of sum<br />
+ AH 1,Two Increment binary part of sum<br />
+ ZAP DWrd0009,Three Increment decimal part of sum<br />
+ AH 1,Two Increment binary part of sum<br />
+ AP DWrd0009,Three Increment decimal part of sum<br />
+ A 1,One Increment binary part of sum<br />
+ CVB 0,DWrd0009 Get binary sum of dec summands<br />
+ AR 1,0 Add to sum of binary summands<br />
+ CVD 1,DWrd0009 Get decimal sum of summands<br />
+ ZAP Three,DWrd0009 Copy to target<br />
+ B DWrd0009+8 Branch around doubleword<br />
+DWrd0009 DS D Scratch area<br />
...<br />
*<br />
One DC F'1'<br />
Two DC H'2'<br />
Three DC PL2'3'<br />
Wrap Up<br />
In Which We Learn That Only<br />
a Small Fraction of the <strong>Macro</strong><br />
<strong>Language</strong> Has Been Covered<br />
41-44
Summary<br />
Two hours is just a start, but a good one<br />
For further information, John Ehrman often<br />
gives sessions at SHARE on advanced<br />
macro techniques: '<strong>Assembler</strong> as a Higher<br />
Level <strong>Language</strong>'<br />
Basic Conditional Assembly and <strong>Macro</strong><br />
Concepts<br />
Applied macro techniques<br />
Some of What Wasn't Covered<br />
Set symbols<br />
Subscripted set symbols and extended Set<br />
statements<br />
SetAF and SetCF<br />
Created set symbols<br />
Many data attributes (length, scaling,<br />
integer, etc.)<br />
Many system variable symbols<br />
&SYSLIST in particular<br />
Some of What Wasn't Covered<br />
Controlling macro expansion listing using<br />
PRINT GEN / NOGEN<br />
Defining macros within macros (!)<br />
Using macros to create job streams<br />
(SYSGEN) - important to understand SMP/E<br />
Using conditional assembly in open code<br />
(outside macros)<br />
Nevertheless...<br />
You now have a basic understanding of<br />
S/390 and z/OS assembler macro language<br />
You have seen what comprises a macro<br />
written in assembler language<br />
And you are ready, if you wish, to begin<br />
writing macros (the best way to learn) and<br />
go on to the next step<br />
So, ...<br />
45-48
Congratulations!<br />
49-52