Hello, I keep getting an error that says no active using statement for the put macro when I call it in an external routine.This is my first time using the open and put macro so I'm sure I'm overlooking something simple.

If QPRNT is defined in one CSECT, and you refer to it in another CSECT, just how are you ensuring addressability of QPRNT across the different CSECT? If your PUT statement is not in the same CSECT as the DCB, you'll need to either establish addressability to QPRNT in some way (which may defeat the purpose of a subroutine), or you'll need to use a register / offset to point to the DCB instead of a name.

If you treat a CSECT like a main program in COBOL or C (the analogy isn't perfect, but it'll do for a beginner), you'll have a better chance of writing code that stands a chance of working.

Before I start. ESPIE is for fairly advanced users. Stay away from it. In more than 44 years of writing /360 Assembler I can count on the fingers of one hand the number of times I've tried SPIE or ESPIE, and they are not used in any finished production program. It's not so much the ESPIE macro; the exit routines will kill you before you can make them do anything useful for you. 128-bit hexadecimal floating point was added to System/360 quite late in the game, just for the Model 85. IBM didn't bother to implement the 128-bit hexadecimal floating point instruction on the Model 85; though they did provide a macro for the division operation, and there was a provision to call the simulation code for division (or for all the 128-bit floating point operations on the other System/360 machines) through a user written SPIE (ESPIE did not yet exist) exit.

There is no conceptual problem putting a DCB in one CSECT and using it in another CSECT. I've done this with a large (1800+ line) program that is close to becoming a frozen production program that I'm working on now. There are two common ways to do this.

Address constants are probably your only choice if the second CSECT is assembled independently of the first CSECT, in which case you would define the DCB as an entry point in the second program, and an external symbol in the first program.

eaglei22 wrote:That did the trick, thanks to both of you, the examples made sense of it.. and I didn't know that (R*) could be passed like that through put.

Your welcome.

Many IBM macros that provide operands that are defined as RX-type symbols can also use registers. An RX-type symbol is a symbol that defines storage that can be used in an RX type instruction. There are a few surprises, though, for example -

PUT DCB,=CL80'FIXED TEXT'

work just great. Of course, you can screw up, too -

PUT =CL8'DCB',=CL80'FIXED TEXT'

will go through the Assembler with no trouble, but you will not get good results if you try to execute the code!

R* symbols

For most of the 44+ years I've been writing /360 Assembler R* symbols were effectively required, not because there was anything magical about them, but because they were listed in the symbol XREF table the Assembler lists. Sometime in the 1990s the Assembler was altered to write the register XREF table, which is superior because it displays implied registers. For example -

TRT DATA,TABLE

potentially alters registers 1 and 2. These registers are shown in the new register XREF table. Like most of my collegues, I kept using R* symbols out of habit, but I no longer bother, simply because the register XREF table is much better than using R* symbols. For a while I'd use R* symbols sporadically, but didn't define them. Oops.

Another issue with R* symbols is, as an example, R1 might not be defined as R1 EQU 1, and this could lead to errors.

Another issue is in the 1960s, we were encouraged to use alias names for registers. The HASP program, for example defined registers like LINK1, LINK2, WA, WB and so on. Through the 1970s and 1980s this convention was quietly forgotten, and you rarely see alias names like these any more because they tend to be confusing.