MainframeSupports
tip uge 29/2012:

Jeg har ikke kodet ret meget assembler i mit liv som programmør, men et af de moduler, jeg har mest glæde af kommer i dette tip. Helt tilbage i uge 21/2001 skrev jeg om, hvordan man i CICS laver et globalt areal, som alle tasks på den pågældende CICS kan dele. For at lave det samme nummer i TSO eller i BATCH (eller et hjemmelavet started task), er du nødt til at lave et assembler-program, der kalder LOAD-macroen. Det er netop, hvad det følgende assembler-program kan.

Hvis du er en meget ivrig læser af mine tip og derudover har en skarp hukommelse, så vil du straks påpege, at metoden beskrevet i uge 28/2005 kan bruges i stedet. Problemet med den metode er, at man kun kan gemme 16 bytes ad gangen. Og så vil du alligevel være tvunget til at allokere et større areal, hvilket nemmest gøres med LOAD:

* NAME : MYLOAD
* FUNCTION : THIS SUBROUTINE LOADS A MODULE INTO STORAGE.
* CALL FMT : CALL MYLOAD(LMODNAME,LMODADDR,DCBADDR,FUNCTION)
* REMARKS :  PROGRAM IS FULLY REENTRANT.
* THE PARAMETERS PASSED TO THIS SUBROUTINE ARE DEFINED AS FOLLOWS:
* LMODNAME DS CL8    THE LMOD NAME SUPPLIED BY THE CALLER.
* LMODADDR DS A      THE ADDRESS IN STORAGE WHERE THE LOADED
*                    MODULE IS RESIDENT.
* DCBADDR  DS A      THE ADDRESS IN STORAGE WHERE THE DCB TO
*                    LOAD PROGRAMS FROM IS LOCATED
* FUNCTION DS F      0=LOAD
*                    <>0=DELETE
*
* REG-15 WILL CONTAIN ONE OF THE FOLLOWING RETURN CODES:
* 0:   LOAD MODULE WAS SUCCESSFULLY LOADED
* 806: LOAD MODULE WAS NOT FOUND
MYLOAD   CSECT
MYLOAD   AMODE ANY
MYLOAD   RMODE ANY
         BAKR R14,0
         BASR R12,0
         USING *,R12
         SR R11,R11
         L R2,0(R1)
         L R3,4(R1)
         L R4,8(R1)
         L R4,0(R4)
         L R5,12(R1)
         L R5,0(R5)
         LTR R5,R5
         BNZ MYLOADD
         LTR R4,R4
         BZ MYLOADN
         LOAD EPLOC=(R2),DCB=(R4),LOADPT=(R3),ERRET=MYLOADZ
         LA R15,0
         B MYLOADR
MYLOADN  EQU *
         LOAD EPLOC=(R2),LOADPT=(R3),ERRET=MYLOADZ
         LA R15,0
         B MYLOADR
MYLOADZ  EQU *
         LA R15,806
         B MYLOADR
MYLOADD  EQU *
         DELETE EPLOC=(R2)
MYLOADR  EQU *
         PR
         LTORG
         YREGS
         END

Nu er assembler ikke særligt læse-venligt, så du må nøjes med en lidt mere udførlig beskrivelse af, hvad de enkelte parametre gør godt for, så du ved, hvordan programmet bruges. Parameteren LMODNAME giver vist sig selv og skal selvfølgelig indeholde navnet på det load-modul, du vil loade ind i storage. Dette load-modul kan med fordel laves som beskrevet i tippet fra uge 21/2001. Det er størrelsen af dette load-modul, der bestemmer, hvor stor et stykke storage, du får allokeret. Parameteren LMODADDR er efter kaldet sat til adressen på load-modulet i storage. Parameteren DCBADDR skal du sætte til 0 inden du kalder programmet, og bevirker at MVS søger efter load-modulet i den sædvanlige søge-rækkefølge. Parameteren FUNCTION sætter du til 0 for at loade. Med DCBADDR og FUNCTION kan du udføre andre snedigheder, men send en mail, hvis du vil vide mere om dem.

Efter kaldet skal du kontrollere returkoden, som enten er sat til 0 for at alting gik godt eller 806 for at load-modulet ikke blev fundet (eller der er fumlet med DCBADDR eller FUNCTION parameteren). Første gang du kalder programmet loades load-modulet som sagt ind i storage. Alle de efterfølgende gange vil LOAD-macroen konstatere, at load-modulet allerede er loadet og nøjes med at returnere adressen på det. En undtagelse er dog, hvis load-modulet har fået attributten NOREUS. Så vil du få loadet load-modulet igen og få en anden adresse retur, og så virker tippet absolut ikke efter hensigten.

Jeg benytter dette tip under ISPF i stedet for ISPF SHARED POOL variable, som desværre kun er globale inden for samme APPLID. Her skal du vide, at når den split session, den første load udføres under dør, så forsvinder load-modulet ud af storage, og dermed forsvinder det globale areal også. Dette er dog under normale omstændigheder ikke noget problem, men det er rigtig godt at vide.

Her til sidst får du lige en stump PLI-kode, der illustrerer brugen af programmet:

DCL myload EXT ENTRY OPTIONS(ASM INTER RETCODE);
DCL lmodName CHAR(8) STATIC INIT('MYLMOD');
DCL lmodAddr POINTER;
DCL dcbAddr POINTER;
DCL function FIXED BIN(31) STATIC INIT(0);
DCL globalArea CHAR(10000) BASED(lmodAddr);

dcbAddr = sysnull();
CALL myload(lmodName, lmodAddr, dcbAddr, function);
IF pliretv() = 0
THEN
  IF substr(globalArea, 1, 10) = 'GLOBALAREA'
  THEN
    PUT SKIP LIST('MYLMOD already loaded');
  ELSE DO;
    PUT SKIP LIST('MYLMOD loaded for the first time');
    globalArea = 'GLOBALAREA';
  END;
ELSE
  PUT SKIP LIST('MYLMOD not found');

Her er det vigtigt at have en eyecatcher i starten af det globale areal, så du kan skelne den første load af MYLMOD fra alle de efterfølgende. I dette eksempel benyttes teksten GLOBALAREA i de første 10 tegn som eyecatcher. Husk at størrelsen af globalArea ikke må være større end størrelsen af MYLMOD, ellers risikerer du en 0C4 abend.

Forrige danske tip        Last tip in english        Tip oversigten