assemblymainframes390x

z/OS Assembler program looping weirdly if output file attributes changed


OK -I'm sure I'm doing something stupid, but I can't see it.

I have a small sample assembler program which I'm going to provide to a colleague who wants to learn assembler, but it has a weird bug I need to iron out first. .

When the output file (DDNAME SYSUT2) is a temporary 80-byte file, it works fine. Change SYSUT2 to SYSOUT=* and it loops from the 'Closing file' WTO.

So here's the program:

//C.SYSLIB   DD  DISP=SHR,DSN=SYS1.MACLIB                               
//           DD  DISP=SHR,DSN=SYS1.MODGEN                               
//           DD  DISP=SHR,DSN=SYS1.ASM.SASMMAC2                         
//*          DD  DISP=SHR,DSN=JOCS065.STEVE.SOURCE                      
-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  4 Line(s) not Displayed 
         TITLE  'TEST PROGRAM'                                          
SYMBOLIC CSECT                                                          
         ASMDREG                      .Register equates                 
         SAVE  (14,12),,'SYMBOLIC PARM SUB &SYSDATE &SYSTIME'           
                                                                        
         LR    R12,R15                .R12 -> entry point               
         USING SYMBOLIC,R12           .Establish addressability         
* Get the parm passed                                                   
         L     R1,0(R1)               .R1 -> parm                       
         LTR   R1,R1                  .Is there one?                    
         BZ    RETURN                 .No - return                      
* We have a parm                                                        
         LH    R2,0(R1)               .R2 = PARM LENGTH                 
         LTR   R2,R2                  .parm length = 0?                 
         BZ    RETURN                 . Yes - return                    
* And the parm has length                                               
         BCTR  R2,0                   .Decrement length for move        
         EX    R2,SETOUT              .Move parm to output              
* Open output file and write parm to output                             
         LA    R4,FILE1            .R4 -> DCB for output file.          
         USING IHADCB,R4           .Establish addressability            
         OPEN  (FILE1,OUTPUT)      .Open log file                       
         TM    DCBOFLGS,DCBOFOPN   .Open successful ?                   
         BZ    BADOPEN             .No - go to error routine            
         WTO   'SIMSG001 OPEN successful.'                              
         DROP  R4                                                       
         WTO   'SIMSG003 writing to file'                               
         PUT   FILE1,OUTREC           .PUT output record                
         WTO   'SIMSG004 Closing file...'                               
         CLOSE (FILE1)                .close files                      
         WTO   'SIMSG005 Returning to caller...'                        
         B     RETURN                 .Return                           
                                                                        
* EXecute instructions                                                  
SETOUT   MVC   OUTREC(0),2(R1)                                          
*****************************************************************       
*                    PROGRAM TERMINATION                                
*****************************************************************       
RETURN   DS    0H                                                       
         WTO   'SIMSG006 RESTORING REGISTERS AND RETURNING'             
         XR    R15,R15                .Clear R15 (RC=0)                 
         RETURN (14,12),RC=(15)       .Restore caller's regs and return 
                                                                        
BADOPEN  DS    0H                                                       
         WTO   'SIMSG002 OPEN failed.'                                  
         B     RETURN                                                   
*****************************************************************       
*                       STORAGE AREAS                                   
*****************************************************************       
OUTREC   DC    80C' '                 .OUTPUT CARD IMAGE                
*****************************************************************       
*                    MACROS AND LITERALS                                
*****************************************************************       
         PRINT NOGEN                                                    
FILE1    DCB   RECFM=F,LRECL=80,BLKSIZE=80,                            X
               DSORG=PS,DDNAME=SYSUT2,MACRF=PM                          
         DCBD                                                           
         PRINT GEN                                                      
*                                                                       
         LTORG                         LITERAL STORAGE                  
         END                                                            
//L.SYSLMOD  DD DISP=SHR,DSN=<your.load.library>(SYMBOLIC)               
//L.SYSPRINT DD SYSOUT=*                                                
//L.SYSIN    DD DUMMY                                                   

and JCL to execute it:

//JOBLIB   DD   DISP=SHR,DSN=<your.load.library>          
//*                                                      
//STEP     EXEC PGM=SYMBOLIC,PARM='THIS IS MY PARAMETER'                                
//SYSUT2 DD SYSOUT=*     

                            

Submit this and the job loops and you have to cancel it. You get 'THIS IS MY PARAMETER' written to SYSUT2 but the WTOs show:

+SIMSG001 OPEN successful.                 
+SIMSG003 writing to file                  
+SIMSG004 Closing file...                  
+SIMSG005 Returning to caller...           
+SIMSG006 RESTORING REGISTERS AND RETURNING
+SIMSG004 Closing file...                  
+SIMSG005 Returning to caller...           
+SIMSG006 RESTORING REGISTERS AND RETURNING
+SIMSG004 Closing file...                  
+SIMSG005 Returning to caller...           
+SIMSG006 RESTORING REGISTERS AND RETURNING
+SIMSG004 Closing file...                  
+SIMSG005 Returning to caller...           
+SIMSG006 RESTORING REGISTERS AND RETURNING
+SIMSG004 Closing file...                  
+SIMSG005 Returning to caller...           
+SIMSG006 RESTORING REGISTERS AND RETURNING

forever.

Change SYSUT2 to :

//SYSUT2 DD DISP=(MOD,PASS),                             
//          DSN=&AMSCNTL,                                
//          UNIT=SYSDA,                                  
//          SPACE=(TRK,1) 

works (I know as I had another step to GENER the temp file to Sysout).

So having FILE1 (SYSUT2) being SYSOUT causes a corruption such that it appears R14 gets restored only to point back to the WTO for the SIMSG004.

This is an old program so it should work. I haven't done much assembler of the last 4 years but have some code using the linkage stack and relative addressing but want to stick with some simple base-displacement code first for teaching this colleague.

Any idea where this is going wrong?


Solution

  • You don't establish a new register save area after saving the registers. So, R13 still points to the same area and the next one saving registers will overwrite, and destroy the the initial return address (and more).

    The PUT macro will call different code for real data sets, and for SYSOUT (JESx) data sets. The difference must be there: If the PUT routine for sysout stores registers at the address in R13, the return address (R14) in the save area will now be the instruction after the PUT. Thus the loop.

    For non-reentrant code this should look like this at entry:

             ...
             LR    R12,R15                     .R12 -> entry point               
             USING SYMBOLIC,R12                .Establish addressability      
    
    * Establish addressability to new save area and chain the save areas
             ST    R13,SAVEAREA+4               Set backward chain pointer
             LR    R15,R13
             LA    R13,SAVEAREA                 Let R13 point to new SA
             ST    R13,8(,R15)                  Set forward chain pointer
    

    And before retuning, get back addressability to caller's SA:

    RETURN   DS    0H
             ...
    
    * Establish addressability to caller's SA
             L     R13,4(,R13)
    
             XR    R15,R15                .Clear R15 (RC=0)                 
             RETURN (14,12),RC=(15)       .Restore caller's regs and return 
    

    Finally, you need to define your own save area:

             ...
    *****************************************************************       
    OUTREC   DC    80C' '                 .OUTPUT CARD IMAGE                
    *****************************************************************    
             ...
    SAVEAREA DS    18F
             ...