Assembler Language Programming Techniques
It is generally important in any computer program to avoid coding any procedure more times than necessary. It is generally best to write something one time, then have it available for later use in may part of a program. In assembler language, there are three main ways of doing this: macros, internal subroutines, and external subroutines. This write-up describes each of these techniques, gives the advantages and disadvantages of each, and notes under what condition each is best.
1. Description, Definition, and Calling
2. Macro Instructions
A macro instruction is defined, and either placed at the beginning of an assembly language program (a user macro), or entered into a macro library. When called, it generates zero or more assembly language statements at the point of invocation, and the code generated may vary greatly from call to call.
A macro definition begins with MACRO, followed by the prototype statement, which gives the name of the macro. The body of the macro includes zero or more model statements, which are assembler commands and machine instructions to be generated, and macro-operations, which server to direct the expansion processing of the macro. The macro definition is terminated by the MEND statement. The following steps are typical in defining a macro:
Internal subroutines are sections of code written as parts of a given control section (CSECT), and are only used inside that CSECT. Like external subroutines, internal subroutines can of course call others. They are typically used for small to medium sections of code which are needed at several palaces in a CSECT, but are not needed by any other, or are not big enough to warrant the overhead in linking them external subroutines.
· Definition - It is often typical to place a group of internal subroutines near the then of the code section of a program (just before the data areas). It is a good idea to set up conventions for the use of internal subroutines, before writing any. The following are often needed: return register, argument registers, and work registers, which can be used without saving. In genera, internal subroutines should not need to do much saving and restoring of registers. They should be able to return via a branch on register (BR) instruction.
· Invocation - Calling an internal subroutine is usually done by first filling any argument registers with needed values, then coding: BAL REG,NAME this type of linkage can be fast and small.
1. External Subroutines
· Definition - An external subroutine may be written in either of two ways in assembler language. As a CSECT or as an entry within a CSECT. In the first case, the subroutine is entered at the CSECT statement and return at one or more places depending on the desired code. In the second case each entrypoint may be give control, and my share code or be totally separate from the other entries. This form is often used for a group of related subroutines (like SIN and COS, which are both entries in a CSECT), or for a routine requiring initialization or termination functions different from the normal calling function.
A multiple-entry CSECT is typically set up as follows:
ENTRY ENTRY1,ENTRY2,ENTRY3 ENTRYn
.. .. .. code for main entry in CSECTNAM
ENTRY1 LINKAGE CODE (SAVE,XSAVE, ETC)
.. .. .. code for ENTRY1 in the main CSECT
ENTRY2 LINKAGE CODE (SAVE2, ETC)
.. .. .. code for ENTRY2 in the main CSECT
ENTRYn LINKAGE CODE (SAVEn, ETC)
.. .. .. code for ENTRYn in the main CSECT
The following are important points to remember when using multiple entry CSECTS:
The different entry points never call each other. In essence, all of the routines represented by the various entry points are at the same level in calling structure of an entire program.
For non-reentrant routines, only one save area is actually needed. Since the routines inside the CSECT never call each other, the user can code the save area at the end of the last section of code, so that all of the previous sections can refer to it (note that if placed at the end of the first CSECT, it would be difficult for the later CSECTs to have addressability to it.
Care must be taken with addressability. All of the code sections can of course address the data areas at the end of the CSECT. However, the programmer must be very careful with any internal subroutines he/she write, because the base registers used to assemble internal subroutines must have the correct values in them at execution time. If they dont, as when they are called from different sections having different using setups, they will assemble properly and then ABEND at execution time. In particular, the programmer should place instructions to be executed (EX instruction) with the section of code using them, and not with the data areas. Thus it is important to DROP base registers when they are no longer needed.
The problems described above are typically handled either buy making all entry point code segment set up the save using conditions, or by setting a specific register to point to the beginning of the internal subroutines, executed instructions and data. If register 13 points to a save area just above these code sections, it can be used this way, since it will always have that save value. Getting the save using conditions across an entire multi-entry CSECT can be done as follows:
In some cases, the calling sequence to invoke an external subroutine essentially includes the CALL macro or equivalent code, i.e. it uses standard conventions. It typically assumes that registers 0,1,14,15 may be modified without causing trouble. This method is efficient and general, but can cause trouble if used improperly. This should be avoided if you dont fully understand your code.
In some cases, it may be useful to define a macro instruction which invokes a subprogram, but can be used anywhere without disturbing any registers, changing the condition code, or requiring that certain of the registers not be the ones being used as base registers (in particular, register 15). The following shows the general form of such a linkage setup, giving first the kind of code to be generated by the macro part, then the entry and exit code for the associated routine:
STM R14,R0,LABLE SAVE THE REGS TO BE CHANGED
. . ELALUATE ARGUMENTS OF THE MACRO
. NOTE THAT ANY REQUIRED LOAD ADDRESS MUST BE DONE
. USING LA 0, ARGUMENT SINCE DOING A LA INOT ANY OTHER
. REGISTER COULD DESTROY A BASE REGISTER. IF MORE THAN
. . ONE ARGUMENT IS NEEDED, THE REMAINING ONES CAN BE
. STORED INTO CONTROL BLOCKS AFTER LABLE.
. AFTER ALL ARGUMENTS ARE EVALUATED AND SAVED, AND
. ONLY THEN, IT IS NOT POSSIBLE TO MODIFY REGISTERS:
L R15,LABEL-4 V-TYPE ADDRESS DEFINITION
CNOP 2,4 ALIGN TO A FULL WORD BOUNDRY
BLAR R14,R15 CALL ROUTINE, ALSO POINT R14 AT
* THE ARGUMENT LIST FOLLOWING
. MORE CODE
DC V(SUBROUTINE) POINTER TO SUBROUTINE
LABEL DS 3F 3 WORDS FOR SAVING REGS 14,15,0
. DS OR DC SPACE HERE FOR ANY REMAING ARGUMENTS
. THE SUBROUTINE WILL RETURN CONTROL TO THE NEXT
LM R14,R0,4(R14) RELOAD REGISTERS. NOTE THAT THIS IS
* ONLY SAFE WAY, SINCE R15 MIGH HAVE
* CURRENT BASE REGISTER.
The following show the typical code used to enter and exit the supporting module used with the previous macro expansion. Note that the entry point of the routing might be either a CSECT name, or an entry name i.e. one CSECT might contain server entry points, one for each supporting subroutine needed.
ENTRY LABEL DEFINITION (CSECT, OR LABEL DS 0H)
USING ENTRY,R15 USER R15 FOR INITIAL BASE REGISTER
. SAVE ALL REGISTERS, WHICH MAY BE MODIFIED BY CODE. SAVE
. INTO THIS CSECT (UNLIKE NORMAL OS CONVENTIONS)
. DO NOT SAVE INTO CALLERS SAVE ARA, SINCE IT MAY NOT
. EXIST, ESPECIALLY IF CALLER IS A LOWEST-LEVEL ROUTINE
. INITIALIZATION CODE: IF THIS ROUTINE PRERFORMES I/O, OR
. CALLS ANY OTHERS, OR REQUIEST ANY SUPERVISOR SERVICES, IT
. . IS NECESSARY TO SETUP A SAVE AREA, AND PUT IS ADDR INOT REG 13
. SINCE ANY OF THE ABOVE ACTIONS MY RESULT IN REGISTERS
. BRING SAVEED AT WHEREVER REGISTER 13 POINTS.
. PROCESSING CODE TO PERFORM REQUIRED ACTIONS
. RESULT RETURN CODE: RESULT MAY BE LEFT IN REGISTER 0
. IN WHICH CASE IT SHOULD NOT BE RESTORED (NEITHER HER NORE
. . IN GENERATED CODE BEOFRE: I.E. CHAN lm r14,r0,4(R14)
. TO LM R14,R15,4(R14) AND STM LIKEWISE).
. REGISTER RESTORATIN: RESORE ALL REGISTERS MODIEF IN THIS
. ROUTINE. ESPECIALY RESTORE REG 14 (RETURN REGISTER)
SPM R14 RESTORE ORIGINA CONDITION CODE (NOTE
* THAT CALLING BALR R14,R15 SAVE IT)
B NUMBER(R14) BRANCH TO DISPL. NUMBER BEYOND
* ADDRRESS IN REG 14 ENOUGH TO PASS
* CONTROL TO STATEMENT: LM R14,R0,4(R14)
It may be useful for the programmer to create a DSECT, which describes the control block generated by the macro expansion. This would permit the module to refer to arguments and return points using symbols rather than absolute displacement.
3. Advantages and Disadvantages
The information on this site is the combined effort of a lot of people,
please credit the authors if you use their information.