ALC Techniques

Home Up Search Credits Site Map Contact Info. Links Disclaimer Download

horizontal rule

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.

 

  1. Definition

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:

    bulletDetermine basic purpose and generated code:  It is generally a good idea to write at least some of the statements to be generated together as a code segment first, to get some feel for what is needed.

 

    bulletDecide on necessary arguments and their usage:  It may be a good idea to write the purpose of each argument in the operand list, list it and include it in a block of comments at the beginning of the macro.  This helps the macro to be done to do what it is supposed to do.

    User positional operands for heavily used arguments, i.e. if an argument must be supplied every time, make it positional.  In a group of positional, place the most heavily used ones near the front, since it is much more convent to omit the later ones than the earlier ones.  Use keyword arguments for values, which may not be needed always, or for ones, which are conveniently supplies with default values, which are most often used.  Use subsists or &SYSLIST for variable numbers of arguments.

 

    bulletWrite actual body of a MACRO, building macro-type commands around the model statements to be generated.
  1. Internal Subroutines
    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
External subroutines are used for major program segments, and can usually be assembled separately from the rest of the program.  In fact they can be written in a different language (i.e. FORTAN and assembler combinations).

·        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:

 CSECTNAM CSECT

                        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 don’t, 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:

ENTRYn            SAVEMACRO

                        L          BASEREG,=A(CSECTNAM)

                        USING CSECTNAME,BASEREG

 

  1. Combined Form – Standard linkage

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 don’t fully understand your code.

 

  1. Combined Form – Special nondestructive Linkage

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.

 

Examples:

 

                    LA                    R0,ARGUMNT

                    ST                    R0,LABEL+12

….               ….                    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

….               ….                    INSTRUCTION:

                    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 CALLER’S 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 following lists the good and bad points of each type of calling convention.

 

4.          Macro Instructions

Code can be tailored to each individual request, i.e. the code generated by each macro call can vary from a great deal to nothing,  such as debug code eliminated by testing a global set variable.

 

Speed:  Macro-generated code can be the fastest in execution, since it can perform it actions without having to set up linage to another section of code.

 

Variability:            Generated code can vary depending on the nature of the arguments passed to a macro (such as testing the type of arguments to generate different instructions).

 

5.          Disadvantages

 

Slow Assembly:            Macro processing can be very slow.

 

Large code:                  if used improperly, macros can generate large amounts of code very easily.  If there are many copies of large blocks of code, much space can be wasted.  (not this was written when a very large system had a waaping 16Megs of storage).

 

Object Decks:              A macro cannot be assembled and an object desk of it gotten like a subroutine can, i.e. if a call is make to a macro, the macro definition must be included in the program or in a library,  while a CSECT may be saved as an object desk or load module (which is usually much smaller then the source desk).

6.          Internal Subroutine

7.          Advantages

Speed:              Although not as fast as in-line code from a macro, the code for an internal subroutine is usually faster than the linkage to an external one.  In particular, values can be passed in registers, and usually registers will not have to be saved.

Space:              Internal subroutines require less space than generating the same code several times via macro expansion.

8.           Disadvantages

Space:              If the same function is performed by internal subroutines in several CSECTS, code is thus duplicated and space wasted.

Complexity:            In some cases, in order to make efficient use of a number of internal subroutines, it is necessary to setup fairly extensive rules on usage of registers in a CSECT, so that the linkage among them my be fast and small.

 

9.          External Subroutines

Advantages

Space:              If written as an external subroutine, code can be usefully called from almost anywhere in a program.  Thus, there is only one copy of it, and it generally will occupy the least space.

 

Separate compile/assembly:         A routine written as a CSECT can be assembled separately from the rest of the program.  The code can be saved as an object desk or a load module.  This will save time reassembling the code for each execution. 

 

Disadvantages
Linkage Time;               if standard Operating System linkage is followed, a fair amount of execution time and object code space can be consumed by this linkage.  More efficient non-standard linkage can be used instead, but this is very dangerous if the non-standard rules are not followed.

 

Combined Forms

 

Advantages

In general, the combined forms can possess all the advantages of the separate forms especially since the Macro ports can generate different code depending on circumstances; thus the code for the same macro might expand in-line in one case and generate an out-of-line call to a routine in another.

Disadvantages

Complexity:            it of course requires somewhat more planning and code to set up a good combined form system, since both a macro and module must be created together properly.

 

Circumstances favoring use of the Various Forms

 

Macro Instructions

In general, a pure macro instruction is used as follows:

Varying code: the required code varies radically form call to call.

 

Short Code: if a macro can generate less in-line code to perform the request function than is needed to generate a call to the routine, then it should be written as a macro.  In some cased, it takes as much work to setup the arguments as it does just to perform the operations.  For example: the code to obtain the minimum or maximum of several arguments is probably more efficiently written as an in-line macro.

 

Linkage code:            Code for linking to routines is almost necessarily written as a macro, since it make little sense to call a routine in order to perform linkage, unless the linkage code requested is very complex.

 

Internal Subroutines

 

Internal subroutines are usually used (as opposed to macros which generate code in-line) under the following circumstances:

 

Code with little variance: if the code is not going to be much different from macro call to macro call, it may be better to let the macro call generates a BAL to one copy of the code as an internal subroutine.

 

Internal subroutines are usually used (as opposed to external subroutines)  under these circumstances:

 

Short code, heavily used:  If code must be used many times by a CSECT, then the faster linkage of internal subroutines usually make it worth writing it that way.

 

Code needed only by one CSECT:  If not too long, it is fairly logical to incorporate it as part of that CSECT.  It will probably be much more efficient since it will have access to the internal variables of the CSECT, and be able to communicate via register value easily, rather than requiring long operand lists

 

External Subroutines

 

Long code:  If something is long and complex enough, it may be a good idea to make a separate module of it, test it, get an object des, then leave it along thereafter.

 

Code of General use, needed many places:  In this case, it is practically necessary to be make code an external subroutine, so that it can be accessed where needed.

 

Combined Forms

 

There are useful anywhere the others are.  The nondestructive form is especially useful if it is to be used by beginning programmers.

 

Credits:  This document was a green-bar listing found from about 1972.  It appears to be from the Pennsylvania State University.  This section was authored by John R. Mashey (1972)

horizontal rule

The information on this site is the combined effort of a lot of people, please credit the authors if you use their information.
Please read the Disclaimer page for the restrictions, copyright, and other uses of the information contained on this site.
For problems or questions regarding this web contact Bob.
Last updated: November 26, 2003.