如果输出文件属性更改,z/OS 汇编程序会奇怪地循环

Posted

技术标签:

【中文标题】如果输出文件属性更改,z/OS 汇编程序会奇怪地循环【英文标题】:z/OS Assembler program looping weirdly if output file attributes changed 【发布时间】:2021-03-23 13:01:10 【问题描述】:

好的 - 我确定我在做一些愚蠢的事情,但我看不到它。

我有一个小型汇编程序示例,我将提供给一位想学习汇编程序的同事,但它有一个奇怪的错误,我需要先解决。 .

当输出文件 (DDNAME SYSUT2) 是一个 80 字节的临时文件时,它可以正常工作。将 SYSUT2 更改为 SYSOUT=*,它会从 'Closing file' WTO 循环。

所以这是程序:

//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                                                   

和 JCL 来执行它:

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

                            

提交此作业循环,您必须取消它。您将“这是我的参数”写入 SYSUT2,但 WTO 显示:

+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

永远。

将 SYSUT2 更改为:

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

有效(我知道我还有一步将临时文件生成到 Sysout)。

因此,将 FILE1 (SYSUT2) 设置为 SYSOUT 会导致损坏,因此看起来 R14 被恢复只是为了指向 SIMSG004 的 WTO。

这是一个旧程序,所以它应该可以工作。在过去的 4 年中,我没有做过太多的汇编程序,但是有一些使用链接堆栈和相对寻址的代码,但我想先坚持使用一些简单的基位移代码来教这个同事。

知道这是哪里出了问题吗?

【问题讨论】:

抱歉 - 程序只是将 PARM 上的所有内容复制到 SYSUT2。 您介意接受其中一个答案吗? @phunsoft 很抱歉 - 因为这是一个小项目,所以在工作中分心了。 【参考方案1】:

保存寄存器后没有建立新的寄存器保存区。所以,R13 仍然指向同一个区域,下一个保存寄存器将覆盖,并破坏初始返回地址(以及更多)。

PUT 宏将为真实数据集和 SYSOUT (JESx) 数据集调用不同的代码。一定有区别:如果 sysout 的 PUT 例程将寄存器存储在 R13 中的地址,则保存区域中的返回地址 (R14) 现在将是 PUT 之后的指令。因此循环。

对于不可重入代码,在入口处应如下所示:

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

在重新调整之前,恢复调用者 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 

最后,你需要定义自己的保存区域:

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

【讨论】:

所以我需要为任何被调用的例程提供一个区域来存储我的寄存器?也许NEWSAVE DC 18F 在我的存储区域中,开头是LA R13,NEWSAVE? SAVE 和 RESTORE 宏不提供这个? 找到这个:ibm.com/support/knowledgecenter/SSLTBW_2.1.0/…。以前我使用过其他人编写的一些宏来完成这一切,所以从来没有真正由自己的寄存器保存/恢复编码 我建议阅读“z/OS MVSProgramming: Assembler Services Guide”,关于链接的章节。 [ibm.com/support/knowledgecenter/SSLTBW_2.1.0/…这里有不可重入代码、重入代码等的所有细节。 SAVE 和 RESTORE 宏不提供此功能?不,它们不提供。【参考方案2】:

与@phunsoft 的答案相同,但原因更多。 WTOOPEN 执行 SVC,因此不需要保存区域; CLOSE 也是。但是,PUTbranch and set register。您需要分配一个 72 字节的 SAVEAREAGETMAIN,一个或任何您想要的。如果您将它放在现有的CSECT 中,它不会重新进入,但那是另一天。这意味着,当您返回时,它会尝试重新加载您未分配的SAVEAREA,并在您的循环来自的PUT 之后立即返回。

在我的系统上是

.PUT output record
 000000A6 4110 C1D0               000001D0     78+         LA    1,FILE1                           LOAD PARAMETER REG 1   02-IHBINNRA
 000000AA 4100 C180               00000180     79+         LA    0,OUTREC                          LOAD PARAMETER REG 0   02-IHBINNRA
 000000AE 1FFF                                 80+         SLR   15,15               CLEAR REGISTER FOR ICM      @L1A 01-PUT
 000000B0 BFF7 1031               00000031     81+         ICM   15,7,49(1)      LOAD PUT ROUTINE ADDRESS        @L1C 01-PUT
 000000B4 0DEF                                 82+         BASR  14,15               LINK TO PUT ROUTINE         @L3C 01-PUT

所以PUT 保存在原来的保存区域,当发出返回时,你会跳回到 PUT 返回之后。

好吧,我忍不住了。这是一个更好的序言

             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  

在序言中添加这些

             GETMAIN LV=72
             ST     R13,4(R1)
             LR     R13,R1

然后,在结语

             LR     R2,R13
             FREEMAIN LV=72,LA=(R2)                 
             L      R13,4(R13)
             LM     R14,R12,12(R13)
             LA     R15,0                    
             BR     R14   

SR,与 XRLA,但辩论所消耗的时间远远超过任何时钟周期。

所以,这就是您需要 SAVEAREA 的原因。但由于这是一个 OG 24 位汇编程序,您无需担心。它曾经是 16MB 就足够了。看起来 JES2 拦截了 SYSOUT 并做了一些魔术,但无论您的 DD 偏好如何,上述方法都可以正常工作。

我希望 JES 不相信任何人会正确地执行 SAVEAREA,这就是我会做的

【讨论】:

IHMO,在退出前释放动态获得的存储不是一个选项,而是一个必须。不这样做会导致存储泄漏。不管它咬你的可能性有多大,不这样做是不好的编程习惯。因此,为了让其他人阅读您的帖子,我建议您将FREEMAIN 添加到您的示例中。 让我感到羞耻 @phunsoft 添加了 FREEMAIN :) 我很抱歉。无意冒犯! @phunsoft 无需道歉。这是正确的选择。我很懒惰。谢谢

以上是关于如果输出文件属性更改,z/OS 汇编程序会奇怪地循环的主要内容,如果未能解决你的问题,请参考以下文章

从 z/OS 上的 C 语言可执行文件中删除符号信息

z/OS 如何调用 Web 服务? [关闭]

在 z/OS 上使用 SSH.NET 通过 SSH 更改密码命令

z/OS 中的 BPXBATCH 实用程序 - 执行 jar 文件

为啥按钮只会在手动更改输入后更改对象属性?

更改在 z/OS USS 中运行的 REXX exec 中的目录?