Assembly 如果输出文件属性发生更改,z/OS汇编程序将异常循环

Assembly 如果输出文件属性发生更改,z/OS汇编程序将异常循环,assembly,mainframe,s390x,Assembly,Mainframe,S390x,好吧,我肯定我在做傻事,但我看不出来 我有一个小样本汇编程序,我将提供给一位想学习汇编程序的同事,但它有一个奇怪的错误,我需要先解决 当输出文件(DDNAME SYSUT2)是一个80字节的临时文件时,它可以正常工作。将SYSUT2更改为SYSOUT=*并从“关闭文件”循环 下面是节目: //C.SYSLIB DD DISP=SHR,DSN=SYS1.MACLIB // DD DISP=SHR,DSN=SY

好吧,我肯定我在做傻事,但我看不出来

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

当输出文件(DDNAME SYSUT2)是一个80字节的临时文件时,它可以正常工作。将SYSUT2更改为SYSOUT=*并从“关闭文件”循环

下面是节目:

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

将SYSUT2更改为:

//SYSUT2 DD DISP=(MOD,PASS),                             
//          DSN=&AMSCNTL,                                
//          UNIT=SYSDA,                                  
//          SPACE=(TRK,1) 
工作正常(我知道我有另一个步骤将临时文件生成为Sysout)

因此,将FILE1(SYSUT2)设为SYSOUT会导致损坏,因此R14似乎只恢复到指向SIMSG004的WTO

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


知道哪里出了问题吗?

保存寄存器后,您不会建立新的寄存器保存区域。因此,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
在重新调谐之前,将addressability返回到调用方的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
         ...

和@phunsoft的答案相同,但有更多的原因。
WTO
OPEN
执行SVCs,因此不需要保存区域<代码>关闭也关闭。但是,
PUT
是一个
分支和设置寄存器
。您需要分配一个72字节的
SAVEAREA
,或
GETMAIN
,一个或以您想要的方式分配。如果您将其放置在现有的
CSECT
中,则它不会重新进入,但这是另一天。这意味着,当您返回时,它会尝试重新加载您未分配的
保存区域,并在
放置之后返回,这就是循环的来源

在我的系统中是这样的

.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
保存在原始保存区域,当发出return时,您可以在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
,与
XR
相比,与
LA
相比,但争论所消耗的时间远远超过任何时钟周期

所以,这就是为什么需要一个存储区。但由于这是一个OG 24位汇编程序,所以您不必担心。以前是16MB就足够了。看起来JES2截获了SYSOUT并做了一些神奇的事情,但是不管您的DD偏好如何,上面的操作都会起作用


我希望JES不相信任何人会正确地保存区域,这也是我会做的

对不起-程序只是将PARM上的任何内容复制到SYSUT2。您介意接受其中一个答案吗?@phunsoft对此表示抱歉-在工作中分心,因为这是一个小的辅助项目。因此我需要为任何调用的例程提供一个区域来存储我的数据登记?可能是
NEWSAVE DC 18F
在我的存储区域中,一开始有
LA R13,NEWSAVE
?保存和还原宏不提供此项?找到此项:。在此之前,我使用过一些由其他人编写的宏来完成这一切,因此从未真正使用自己的寄存器save/restore进行编码。我建议您阅读“z/OS MVSProgramming:Assembler Services Guide”(z/OS MVSProgramming:Assembler Services Guide)中有关链接的章节。[这包含了非可重入代码、可重入代码等的所有详细信息。保存和还原宏不提供这些信息?不,它们不提供。IHMO,在退出之前释放动态获取的存储不是一个选项,而是一个必须的选项。不这样做会导致存储泄漏。不管它咬你的可能性有多大,不这样做都是不好的编程练习。为了让其他人阅读你的帖子,我建议你在你的例子中添加
FREEMAIN
。让我感到羞耻@phunsoft添加了FREEMAIN:)我的道歉。没有冒犯意味着!@phunsoft没有必要道歉。这是正确的选择。我很懒。谢谢
             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