laird@chinet.chi.il.us (Laird J. Heal) (02/27/91)
In article <9102261052.AA16278@ucbvax.Berkeley.EDU> IBM 370 Assembly Programming Discussion List <ASM370@OHSTVMA.BITNET> writes: > >My girl friend starts to working with system 370 assembler. >But she don't care syntax and rules of 370 assembly ! There are really very few bad practices in 370 assembler, or perhaps there are really very few good practices in 370 assembler. Now that I sound confused too, let me lay down a few rules, of thumb that is. Since registers zero, one and two can be modified by everything from SVCs to TRTs, use them for scratch areas. R15 is your entry address but you should save it off - R12 is typically used for this and thus as the code base register. R14 is the return address but can be used within your code as can R15, as the OS never really relies on them. R13, on the other hand, should always point to your Register Save Area, unless you are working with DOS/VSE/POWER, in which case I commend your soul to the appropriate power. Always observe register saving and save area chaining scrupulously. That is, use the SAVE and RETURN macros or write code yourself to put R14-R12 at 12(R13), then save the address of your area in the caller's area and save hers in yours. Note: a calling process is generally called the `mother' process. All other registers can be used for base or scratch as you like. Writing reentrant code (use RU-type GETMAIN for all data areas) is good practice but not much good otherwise. Always use DS 0H for all branch labels. There was a much better reason once (in the days of punch-cards) but now it just helps to clarify the scene. Never write self-modifying code - there is always a better way to accomplish the same thing, generally with a table of things to pick up and EXECUTE with, if your program is so constituted. Have fun. -- Laird J. Heal The Usenet is dead! Here: laird@chinet.chi.il.us Long live the Usenet!
laird@GARGOYLE.UCHICAGO.EDU ("Laird J. Heal") (02/27/91)
In article <9102261052.AA16278@ucbvax.Berkeley.EDU> IBM 370 Assembly Programming Discussion List <ASM370@OHSTVMA.BITNET> writes: > >My girl friend starts to working with system 370 assembler. >But she don't care syntax and rules of 370 assembly ! There are really very few bad practices in 370 assembler, or perhaps there are really very few good practices in 370 assembler. Now that I sound confused too, let me lay down a few rules, of thumb that is. Since registers zero, one and two can be modified by everything from SVCs to TRTs, use them for scratch areas. R15 is your entry address but you should save it off - R12 is typically used for this and thus as the code base register. R14 is the return address but can be used within your code as can R15, as the OS never really relies on them. R13, on the other hand, should always point to your Register Save Area, unless you are working with DOS/VSE/POWER, in which case I commend your soul to the appropriate power. Always observe register saving and save area chaining scrupulously. That is, use the SAVE and RETURN macros or write code yourself to put R14-R12 at 12(R13), then save the address of your area in the caller's area and save hers in yours. Note: a calling process is generally called the `mother' process. All other registers can be used for base or scratch as you like. Writing reentrant code (use RU-type GETMAIN for all data areas) is good practice but not much good otherwise. Always use DS 0H for all branch labels. There was a much better reason once (in the days of punch-cards) but now it just helps to clarify the scene. Never write self-modifying code - there is always a better way to accomplish the same thing, generally with a table of things to pick up and EXECUTE with, if your program is so constituted. Have fun. -- Laird J. Heal The Usenet is dead! Here: laird@chinet.chi.il.us Long live the Usenet!
VALDIS@VTVM1.CC.VT.EDU (Valdis Kletnieks) (02/28/91)
On Wed, 27 Feb 91 04:32:34 GMT Laird J. Heal said: >Since registers zero, one and two can be modified by everything from >SVCs to TRTs, use them for scratch areas. R15 is your entry address >but you should save it off - R12 is typically used for this and thus >as the code base register. R14 is the return address but can be used >within your code as can R15, as the OS never really relies on them. >R13, on the other hand, should always point to your Register Save >Area, unless you are working with DOS/VSE/POWER, in which case I >commend your soul to the appropriate power. Please note that at least in OS/MVT and VS/1 and (presumably) the various MVS variants, and the OS Simulation routines under VM/CMS, that the various QSAM I/O macros (such as GET and PUT), involve a BALR 14,15 - so these registers should *not* be used except as scratch unless you *know* that any system macros you use don't modify these registers. Incidentally, macros like this are the *REASON* you usually use R12 as the base rather than R15.... Valdis Kletnieks Computer Systems Engineer Virginia Polytechnic Institute
ralerche@lindy.stanford.edu (Robert A. Lerche) (02/28/91)
laird@chinet.chi.il.us (Laird J. Heal) writes: ... >Always observe register saving and save area chaining scrupulously. >That is, use the SAVE and RETURN macros or write code yourself to >put R14-R12 at 12(R13), then save the address of your area in the >caller's area and save hers in yours. Note: a calling process is >generally called the `mother' process. In OS the common entry sequence is... MODULE CSECT SAVE (14,12),,* LR R12,R15 (OS PROVIDES MY ENTRY POINT IN R15) USING MODULE,R12 LR R2,R1 PRESERVE PARM POINTER ACROSS GETMAIN GETMAIN R,LV=SVLENGTH MINIMUM LENGTH IS 72 FOR A SAVE AREA ST R13,4(,R1) BACK-CHAIN NEW TO OLD SAVE AREA ST R1,8(,R13) FWD-CHAIN OLD TO NEW SAVE AREA XC 8(4,R1),8(R1) CLEAR FWD CHAIN OF NEW SAVE AREA LR R13,R1 OK -- SAVE AREA ALL SET UP >All other registers [besides 0, 1, 2, 13, 14 and 15] >can be used for base or scratch as you like. >Writing reentrant code (use RU-type GETMAIN for all data areas) >is good practice but not much good otherwise. Actually R2 is not used by any usual operating system functions, so it's safe too (though the TRT instruction does use it as an implicit operand). Reentrant code is not that hard to do, and besides being good practice it is critical if you ever use multiple tasks. An easy way to arrange the data areas is to make your save area (gotten above via GETMAIN) include them after the register save area. E. g., USING R13,SAVEAREA ... SAVEAREA DSECT DS 18F STANDARD OS SAVE AREA <writable data areas go here> SVLENGTH EQU *-SAVEAREA TOTAL LENGTH OF GETMAIN'ED AREA You also need to learn about the MF=E forms of the MACROs -- what it amounts to is that the standard forms of some MACROs don't generate reentrant code because they have to create some kind of parameter list, so they put it directly in the code and branch around it. Those MACROs all provide an MF=L form to generate the parameter list (as a constant) and an MF=E form to fill it in and execute the operation. You copy the MF=L list into your work storage (again, in the GETMAIN'ed area) and use MF=(E,<area>) to point to it. >... Never write self-modifying code - there is >always a better way to accomplish the same thing, generally with >a table of things to pick up and EXECUTE with, if your program is >so constituted. Amen! ----- (other points) Note the use of symbolic names R<n> for the registers. This helps because it causes register references to appear in the cross-reference listing generated by the assembler. In a complex piece of code it can be difficult to follow the register usage; having a listing can help this. A related point: pick a convention for your use of the registers, document it in comments in the beginning of the routine, and STICK TO IT! There is nothing more difficult than keeping track in one's mind of the meaning of all the registers. LOTS of bugs come from failing to notice some subtlety in this area. Finally, remember that no matter how well you write assembler code it is almost always easier to write (and debug!) in a high-level language. If what you are doing requires the use of assembler (e.g., because you need to access some system interface that is only available from assembler), a good approach is to write a small, well-defined subroutine in assembler that can be called from a high-level language.
ralerche@LINDY.STANFORD.EDU ("Robert A. Lerche") (02/28/91)
laird@chinet.chi.il.us (Laird J. Heal) writes: ... >Always observe register saving and save area chaining scrupulously. >That is, use the SAVE and RETURN macros or write code yourself to >put R14-R12 at 12(R13), then save the address of your area in the >caller's area and save hers in yours. Note: a calling process is >generally called the `mother' process. In OS the common entry sequence is... MODULE CSECT SAVE (14,12),,* LR R12,R15 (OS PROVIDES MY ENTRY POINT IN R15) USING MODULE,R12 LR R2,R1 PRESERVE PARM POINTER ACROSS GETMAIN GETMAIN R,LV=SVLENGTH MINIMUM LENGTH IS 72 FOR A SAVE AREA ST R13,4(,R1) BACK-CHAIN NEW TO OLD SAVE AREA ST R1,8(,R13) FWD-CHAIN OLD TO NEW SAVE AREA XC 8(4,R1),8(R1) CLEAR FWD CHAIN OF NEW SAVE AREA LR R13,R1 OK -- SAVE AREA ALL SET UP >All other registers [besides 0, 1, 2, 13, 14 and 15] >can be used for base or scratch as you like. >Writing reentrant code (use RU-type GETMAIN for all data areas) >is good practice but not much good otherwise. Actually R2 is not used by any usual operating system functions, so it's safe too (though the TRT instruction does use it as an implicit operand). Reentrant code is not that hard to do, and besides being good practice it is critical if you ever use multiple tasks. An easy way to arrange the data areas is to make your save area (gotten above via GETMAIN) include them after the register save area. E. g., USING R13,SAVEAREA ... SAVEAREA DSECT DS 18F STANDARD OS SAVE AREA <writable data areas go here> SVLENGTH EQU *-SAVEAREA TOTAL LENGTH OF GETMAIN'ED AREA You also need to learn about the MF=E forms of the MACROs -- what it amounts to is that the standard forms of some MACROs don't generate reentrant code because they have to create some kind of parameter list, so they put it directly in the code and branch around it. Those MACROs all provide an MF=L form to generate the parameter list (as a constant) and an MF=E form to fill it in and execute the operation. You copy the MF=L list into your work storage (again, in the GETMAIN'ed area) and use MF=(E,<area>) to point to it. >... Never write self-modifying code - there is >always a better way to accomplish the same thing, generally with >a table of things to pick up and EXECUTE with, if your program is >so constituted. Amen! ----- (other points) Note the use of symbolic names R<n> for the registers. This helps because it causes register references to appear in the cross-reference listing generated by the assembler. In a complex piece of code it can be difficult to follow the register usage; having a listing can help this. A related point: pick a convention for your use of the registers, document it in comments in the beginning of the routine, and STICK TO IT! There is nothing more difficult than keeping track in one's mind of the meaning of all the registers. LOTS of bugs come from failing to notice some subtlety in this area. Finally, remember that no matter how well you write assembler code it is almost always easier to write (and debug!) in a high-level language. If what you are doing requires the use of assembler (e.g., because you need to access some system interface that is only available from assembler), a good approach is to write a small, well-defined subroutine in assembler that can be called from a high-level language.
laird@chinet.chi.il.us (Laird J. Heal) (03/03/91)
In article <9102272012.AA08264@ucbvax.Berkeley.EDU> IBM 370 Assembly Programming Discussion List <ASM370@OHSTVMA.BITNET> writes: >On Wed, 27 Feb 91 04:32:34 GMT Laird J. Heal said: > >>All other registers [besides 0, 1, 2, 13, 14 and 15] >>can be used for base or scratch as you like. >>Writing reentrant code (use RU-type GETMAIN for all data areas) >>is good practice but not much good otherwise. > >Actually R2 is not used by any usual operating system functions, so >it's safe too (though the TRT instruction does use it as an implicit I find its special status a good excuse to use it as a single scratch register whose contents will not be normally modified by the operating system. There is no special error in using it, for example, as a base register, but I can remember well solving a nightmare for a co-worker by noting that the last byte of R2 was providing him with a little unexpected auto-indexing. >>Since registers zero, one and two can be modified by everything from >>SVCs to TRTs, use them for scratch areas. R15 is your entry address >>but you should save it off - R12 is typically used for this and thus >>as the code base register. R14 is the return address but can be used >>within your code as can R15, as the OS never really relies on them. >>R13, on the other hand, should always point to your Register Save >>Area, unless you are working with DOS/VSE/POWER, in which case I >>commend your soul to the appropriate power. >Please note that at least in OS/MVT and VS/1 and (presumably) the >various MVS variants, and the OS Simulation routines under VM/CMS, >that the various QSAM I/O macros (such as GET and PUT), involve >a BALR 14,15 - so these registers should *not* be used except as >scratch unless you *know* that any system macros you use don't modify >these registers. Incidentally, macros like this are the *REASON* you >usually use R12 as the base rather than R15.... Excuses for the extensive attributions. You note that I was commenting on scratch registers. Simply put, I was cautioning against using R13 for anything except save area chaining. The other registers (from R14 to R2) are not so sacrosanct. Some folks use R2 for a base register or such - I feel this is a mistake of style, but since TRT is not normally used, it often is harmless. During my first class in BAL, the assistant (who was grading all of the exercises) said "always use PRINT GEN" to which the instructor said "you mean, never use PRINT GEN". I tend to the "always" mode. -- Laird J. Heal The Usenet is dead! Here: laird@chinet.chi.il.us Long live the Usenet!
laird@GARGOYLE.UCHICAGO.EDU ("Laird J. Heal") (03/03/91)
In article <9102272012.AA08264@ucbvax.Berkeley.EDU> IBM 370 Assembly Programming Discussion List <ASM370@OHSTVMA.BITNET> writes: >On Wed, 27 Feb 91 04:32:34 GMT Laird J. Heal said: > >>All other registers [besides 0, 1, 2, 13, 14 and 15] >>can be used for base or scratch as you like. >>Writing reentrant code (use RU-type GETMAIN for all data areas) >>is good practice but not much good otherwise. > >Actually R2 is not used by any usual operating system functions, so >it's safe too (though the TRT instruction does use it as an implicit I find its special status a good excuse to use it as a single scratch register whose contents will not be normally modified by the operating system. There is no special error in using it, for example, as a base register, but I can remember well solving a nightmare for a co-worker by noting that the last byte of R2 was providing him with a little unexpected auto-indexing. >>Since registers zero, one and two can be modified by everything from >>SVCs to TRTs, use them for scratch areas. R15 is your entry address >>but you should save it off - R12 is typically used for this and thus >>as the code base register. R14 is the return address but can be used >>within your code as can R15, as the OS never really relies on them. >>R13, on the other hand, should always point to your Register Save >>Area, unless you are working with DOS/VSE/POWER, in which case I >>commend your soul to the appropriate power. >Please note that at least in OS/MVT and VS/1 and (presumably) the >various MVS variants, and the OS Simulation routines under VM/CMS, >that the various QSAM I/O macros (such as GET and PUT), involve >a BALR 14,15 - so these registers should *not* be used except as >scratch unless you *know* that any system macros you use don't modify >these registers. Incidentally, macros like this are the *REASON* you >usually use R12 as the base rather than R15.... Excuses for the extensive attributions. You note that I was commenting on scratch registers. Simply put, I was cautioning against using R13 for anything except save area chaining. The other registers (from R14 to R2) are not so sacrosanct. Some folks use R2 for a base register or such - I feel this is a mistake of style, but since TRT is not normally used, it often is harmless. During my first class in BAL, the assistant (who was grading all of the exercises) said "always use PRINT GEN" to which the instructor said "you mean, never use PRINT GEN". I tend to the "always" mode. -- Laird J. Heal The Usenet is dead! Here: laird@chinet.chi.il.us Long live the Usenet!
SOMITCW@VCCSCENT.BITNET (03/04/91)
On Sun, 3 Mar 91, chinet!laird@GARGOYLE.UCHICAGO.EDU said: >During my first class in BAL, the assistant (who was grading all of the >exercises) said "always use PRINT GEN" to which the instructor said >"you mean, never use PRINT GEN". I tend to the "always" mode. If the class was really BAL, then why were you using PRINT GEN? Note: The last S/360 BAL that IBM had was for the S/360-20. Later, when IBM came out with the MACRO Assemblers, they called them Full Assemblers. Classes that teach assembler without teaching macros are still called BAL, even though there has never been a S/370 BAL product.
LDW@USCMVSA.BITNET (Leonard D Woren) (03/09/91)
> During my first class in BAL, the assistant (who was grading all of the > exercises) said "always use PRINT GEN" to which the instructor said > "you mean, never use PRINT GEN". I tend to the "always" mode. PRINT NOGEN can hide programming errors. Long ago, as a consultant for student programmers, I was presented with an abend S0C4 in low core (yep, it was long ago). It was abending on a PUT to a file. Given the logic flow of the simple program, it was clear that there was no way the open could not have been executed, yet the file wasn't open! Here is the relevant part of what I saw: LA R4,SYSPRINT OPEN (R4) ... LA R4,SYSPRINT PUT (R4),... With PRINT NOGEN, this error is extremely difficult to spot. I told the student to never use PRINT NOGEN around executable code. Leonard D. Woren Senior MVS Systems Programmer <LDW@USCMVSA.BITNET> <LDW@MVSA.USC.EDU> Disclaimer??? University of Southern California What would be the point?