mandag den 31. august 2015

How the assembler works (1)

Understanding the location counter

The primary task for the assembler is to convert your symbolic machine instruction to the actual machine instruction. for instance 
000AC D20F A08A B0C0 0008A 000E0   101          MVC   PGM2_EXEC,PGM2_LIST 

The MVC coresponds to the D2 and that will be all for now. At the very left of the line you will see the position of the instruction according to the other instructions in your program. We could call it the offset to the beginning of the program. Here it is in hexadecimal and the offset is called the Location Counter. It is increased by the length of the present instruction so there is space for the next instruction. Not complicated, - but very important!!

First of all you have to keep in mind that this is on the time of assembling your program. An asterisks (*) refers to the current position of your location counter. 
Here comes an example. The first line A(*+8) means current position (look left) which is X' E0' plus 8 equals X'E8'. That is the location counter of the third line. That will later be resolved into the address of the program name, but that is another story.  
0000E0 000000E8                     130+PGM2_LIST DC   A(*+8)
0000E4 00000000                     131+         DC    A(0)
0000E8 D7C7D4F240404040             132+         DC    CL8'PGM2'
                      00010         133 PGM2_LGD EQU   *-PGM2_LIST
The last line will calculate the length of the three instructions above. This is a pure assembler instruction and will NOT increase the location counter, - i.e. it will never end up as an machine instruction. That is why there is no location counter on the left. The assembler variable PGM2_LGD is calculated to the right of the EQU-instruction (EQUal). 
* is the current value of the location counter and subtract it by the location counter for PGM_LIST. That equals to decimal 16 (X'10'). That is what the left most integer tells you.

It is always better to have the length in an variable, because you might put another field into the DSECT and your length of that DSECT will still be correct.

Length used explicit

You do not need to calculate the length every time. You can use the length as part of your instruction in order to manipulate the assembler to use another lenght. You can always put L' (quote) in front of your field. It will then be an assembler variable containing the length of that field.
000090 D20F A000 B17C 00000 001A0    91   MVC   WSEC,=CL(L'WSEC)'PGM2-WS' 
I wish to move the constant into the field WSEC but I don't know the length of WSEC. It doesn't matter because I will just set the length of the constant to the same as WSEC. The result is that the constant is padded with space to right, - exactly what I want. Take a look at the machine instruction. From the second byte of the instruction you can derive that the length is actually 16, (X'F' + 1).

Take a look at these four instructions and tell me what the second one does,
0000A0 4430 B084            000A8    99          EX    R3,MVC
0000A4 47F0 B08A            000AE   100          B     MVC+L'MVC
0000A8 D200 A016 2002 00016 00002   101 MVC      MVC   WTOTEXT(0),2(R2)
0000AE 4130 A014            00014   102          LA    R3,WTOLGD
Yes, - it branches over the MVC-instruction to the last instruction. The Branch needs an offset and calculates it by taking the location counter of MVC, the label contains both the location counter and length. Both are added together (MVC+l'MVC) and the result 000AE is showen. Look at the last line location counter and you will see it is correct.


lørdag den 29. august 2015

How to make your assembler program reentable

How to make your assembler program reentable

The Linkage Editor or Binder

When I learned assembly language a generation ago, there were two steps in the translation: the assembly and linkage editing. I had no idea what the last one did. I did not consider it important, but in short, Linkage Editor makes your program to the final (load) module, so it can be used by z / Os. Today called the Binder, which corresponds very well to what we call the same function on other platforms. However, there are some important parameters for binder, as you have to keep track of, if not you will have problems.
One of them is reusability, which tells the operating system how the program can be re-used by the operating system. The operating system has many simultaneous "tasks" running, so it is important that the program does not change itself. It might even change its code or values, or others could. If the assembler programmer guarantees that his program does not modify itself (or is modified by others), it could have the label "Reentable". It is a very fine predicate, which tells the operating system that it can load the program into a piece of memory which can be read only. If the program or another, violate the rule, that person thrown by an Abendkode "S0C4".
The operating system looks at "reusability" of each module as it loads it into memory and decides whether to enter the "read only" memory or modifiable memory.
Experienced system programmers will probably remember that one could put more of these predicates on a module, for example. both the "reusable" and "reentable". It should be no more. A load module can only get one predicate:
-------------------------------------------------------------------------------------------------------
Reusability (REUS, RENT and REFR) is handled differently by the binder. While the linkage editor processes the attributes independently, the binder stores them as a single value. The binder assumes that reenterable programs are also serially reusable, and the refreshable programs are also reenterable. This should not cause any processing difficulties.
The binder was designed to always accept an explicit override of a module attribute, whereas the linkage editor sometimes does not. For example, although the JCL can specify RENT in the parm list, when one CSECT being bound into a load module is reusable and the rest are reentrant, the linkage editor ignores the external parameter and assigns the module as reusable. The binder will allow the explicit override of RENT on the JCL to take priority.
------------------------------------------------------------------------------------------------------
From the manual z/OS MVS Program Management: User's Guide and ReferenceBinder processing differences from the linkage editor
If your program is modified anyway during the execution, you should "bind / link" with the REUSE = SERIAL or NONE. In this example, I have said that the module is serial reusable. So it is up to the programmer to manage the changes in the module code or values.
    SETOPT PARM (LET LIST XREF, NCAL, REUS = SERIAL)
    MODE AMODE (24), RMODE (24) NAME [modulename] (R)
The binder writes a list of the values and predicates the module has received. In the example below, the results from the parameters above.
------------------------------------------------------------------------------------------------------
AC               000 
AMODE             24
COMPRESSION     NONE
DC NO EDITABLE   YES
EXCEEDS 16MB      NO
EXECUTABLE       YES
LONGPARM          NO
MIGRATABLE       YES
OL                NO
OVLY              NO
PACK,PRIME     NO,NO
PAGE ALIGN        NO
REFR              NO
RENT              NO
REUS             YES 

RMODE             24
SCTR              NO
SIGN              NO
SSI
SYM GENERATED     NO
TEST              NO
XPLINK            NO
MODULE SIZE (HEX) 000001A0

------------------------------------------------------------------------------------------------------
Note that there are still several lines out regarding reusability, but that is really only in order to be backward compatible. The same also applies if you go into LOADLIB and find the module. Here are also more fields set aside to Reusable, but again, it's just to be backward compatible.
------------------------------------------------------------------------- 
MITPGM1 RU 
MITPGM2 
MITPGM3 RN RU
MITPGM4 RN RU

--------------------------------------------------------------------------

Program MITPGM3 og MITPGM4 are both Reentable, where MITPGM1 is "only" Serial Reusable
I have collected som links if wish to read some mode on the subject:

To be or not to be reentable


In the last chapter I wrote at the end of the article "So it is up to the programmer to manage the changes in the module code or values." I will show how it's done. We must ensure that nothing in the program will be changed. This means that all variables must be located in storage, for each individual process outside of the program; We must therefore make a so-called Getmain - ie retrieve main storage.
          GETMAIN RC,LV=STOR_LGD
          OR R1,R1
          BZ NO_STORAGE_OBTAINED
          LR R10,R1
          USING STORAGE,R10
          MVC EC,=CL(L’EC)’PGM2-STORAGE’

Somewhere in the program outside the control section (the CSECT the one with instructions), insert a DSECT describing your work area.
STORAGE   DSECT
EC        DS     CL16                 EYE CATCHER
VALUE1    DS     F
VALUE2    DS     H
VALUE3    DS     CL120
VALUE4    DS     F
STOR_LGD EQU *-STORAGE

You start to getmaine the area with a length which is calculated by the last instruction in the DSECT. Then you check if there is an address in register 1 (R1) with the OR instruction. If not, then go to the error routine NO_STORAGE_OBTAINED. In the next instruction you move the address into the R10 and then say that when you refer to the fields in this storage, R10 is used. Eventually move a so-called Eye Catcher in front of the area. It's nice if the program will dump its storage. So you can make a "Find" on the Eye Catch Eren, to find the area.

The DSECT describes the look of your space. It starts with DSECT and the name of this DSECT so you can refer to it in the USING. Then come your variables and finally the length of the area is calculated. So we are running ....

Linkage Convensions

Or, in other words, - it was the easy part. There will be more, but right now we issue yet another Getmain which must come very first in the program. It will be needed if we call other programs, so that they can save their registers (R14 to R12) in order to be able to restore them before returning to us. In other operating systems it is called to put on the stack, and retrieve from the stack. In z/OS it is called to comply with Linkage Conventions.

However, we're a program our self that is called - perhaps by the operating system, perhaps by another program. Therefore, we must save the caller's registers. Fortunately, a Macro will do most of it.
          SAVE   (14,12),,'PGM2 - &SYSDATE..&SYSTIME'
The latter is a comment that tells the program name (PGM2) and the time of program assembling. It is not just not recommended, but required that you use it!. It helps tremendously in many cases to make sure we got the right version of the program in a troubleshooting situation. After saving the caller's registers, we need to have a storage area for our registres, if we were to call another program.
RSA      GETMAIN RC,LV=72
         OR    R1,R1
         BZ    NO_STORAGE_OBTAINED
         ST    R1,8(,R13)
         ST    R13,4(,R1)
         LR    R13,R1
         USING SA,R13
         ........
         ........
SA       DSECT
SAVEAREA DS    18F

We pick up 72 bytes, or 18 fullwords (18F). That's all we need. The two Store Instructions (ST) makes a concatenation of register save areas and eventually we let R13 point to our Register Save Area and create adressability to it with USING. Just before we leave the program, we must re-establish the caller's registeres. This is done as follows:
         L     R13,SAVEAREA+4
         LM    R14,R12,12(R13)
         RETURN RC=0
First, R13 points to the callers Register Save Area. Then all registers from this area are fetched - except R13 of course. Finally, we return to the caller. 


Your program is fully reentable and can be laid in the Link Pack Area (LPA). It is a read-only-area, which is accessible to all address spaces (regions). It can also be used simultaneously to multiple tasks / threads. In the next chapter we talk about calling other programs if you still want your program to be reentable. It's not quite that simple as it sounds.

More reading:

Even more about reentable
In last chapter we made a reentrant program and you thought maybe it was everything, but it is not. It turns out that if you have to use some built-in features such as to call another program (LINK), then some of these features actually modify themselves in the program that uses them. I will review an example with LINK.

In my PGM1 I make a LINK to PGM2. I call it with a parameter. Notice the last three instructions that the parameter definition. It is embedded in the program itself. It is  required by the LINK macro, because it generates the address of Parm in A (PARM + X'80000000 '). If I had no PARM or it was a constant in the program, I could have used the standard LINK in a reentrant program.



        STH   R3,PARMLGD              
***************************************
** FLYT VARIABEL LÆNGDE AF TEKST       
***************************************
        BCTR  R3,0                    
        EX    R3,MVC                  
        B     MVC+L'MVC               
MVC      MVC   PARMTXT(0),2(R2)        
PGM2     LINK  EP=PGM2,PARAM=PARM,VL=1                        
PGM2     DS    0H                                             
        CNOP  0,4                                            
        LA    1,IHB0011                         LIST ADDRESS
        B     IHB0011A                          BYPASS LIST  
IHB0011  EQU   *                                              
        DC    A(PARM+X'80000000')                            
IHB0011A EQU   *                                              
        CNOP  0,4                                            
        BAL   15,*+20            BRANCH AROUND CONSTANTS     
        DC    A(*+8)             ADDR. OF PARM. LIST         
        DC    A(0)                DCB ADDRESS PARAMETER      
        DC    CL8'PGM2'           EP PARAMETER               
        SVC   6                   ISSUE LINK SVC             
        B     RETURN                                         
PARM     DS    0F                                             
PARMLGD  DS    H                                              
PARMTXT  DS    CL120                                          

Instead of using one standard LINK, use two - a LIST form and EXEC form. LIST form describes constants and variable fields to the LINK called. The EXEC form performs the actual LINK, just as standard LINK. This means that you define your LIST form along with your other constants and defines an area in your Getmained storage where you can move it up before performing the EXEC form. The macro parameter MF = L says that you want the LIST form and MF = E that you make EXEC form. Note that in MF = E comes the name of the field where you moved LIST form to. It may be a little tricky, but your program is reentrant. And that is beautiful.
STORAGE   DSECT                                     
STORAGE_EYE_CATCHER DS CL16            EYE CATCHER
PARM      DS    0F                                  
PARMLGD   DS    H                                   
PARMTXT   DS    CL120                               
STOR_LGD EQU   *-STORAGE                           
PGM2_EXEC DS   XL(PGM2_LGD)
                      

        STH   R3,PARMLGD                 
******************************************
** FLYT VARIABEL LÆNGDE AF TEKST        **
******************************************
        BCTR  R3,0                       
        EX    R3,MVC                     
        B     MVC+L'MVC                  
MVC      MVC   PARMTXT(0),2(R2) 
******************************************                              
        MVC   PGM2_EXEC,PGM2_LIST                                      
PGM2     LINK  EP=PGM2,PARAM=PARM,VL=1,MF=(E,PGM2_EXEC)                 
PGM2     DS    0H                                                       
*                                                                 1ØL1D
*                                                                 1ØL1D
        LA    1,PGM2_EXEC                       LOAD PARAMETER REG 1   
        LA    14,PARM            PICKUP PARAMETER                      
        ST    14,0(0,1)                         STORE INTO PARAM. LIST
        OI    0(1),X'80'                 SET LAST WORD BIT ON ØG860P40
        CNOP  0,4                                                      
        BAL   15,*+20            BRANCH AROUND CONSTANTS               
        DC    A(*+8)             ADDR. OF PARM. LIST                   
        DC    A(0)                DCB ADDRESS PARAMETER                
        DC    CL8'PGM2'           EP PARAMETER                         
        SVC   6                   ISSUE LINK SVC              ØG381P2A
        B     RETURN                                                   
PGM2_LIST LINK EP=PGM2,SF=L                                             
        CNOP  0,4                                                      
PGM2_LIST DC   A(*+8)             ADDRESS OF EP PARAMETER               
        DC    A(0)           DCB ADDRESS PARAMETER                     
        DC    CL8'PGM2'      EP PARAMETER                              

PGM2_LGD EQU   *-PGM2_LIST                                              


I do not know if you have noticed it, but there's a little wrinkle in my program that I had to use to move the parameter, which can be of variable length. That is the little EX command. It takes the right aligned byte in the register and put it in the second byte of the instruction, as it points to - here MVC. It is a kind of modification of the code, but it is in the CPU and NOT in the program. I could also have used MVCL (Move Long), but it would be too boring and cumbersome.

That was what I know about Reentable programs. Feel free to add notes and idears of how to improve a program regarding reentable. I would really have been pleased if someone had writen such an article for 30 years ago.

tirsdag den 25. august 2015

Mere om at blive reentable ...


Sidste gang lavede vi et reentrant program og så troede du måske, at det var alt, men det er det ikke. Det viser sig nemlig, at hvis man skal bruge nogle indbyggede funktioner, som f.eks. at kalde et andet program (LINK), så modificerer nogle af disse funktioner faktisk sig selv og dermed programmet, der bruger dem. Jeg vil gennemgå et eksempel med LINK.


I mit PGM1 laver jeg et LINK til PGM2. Jeg kalder det med en parameter. Læg mærke til de sidste tre instruktioner, som er parameterdefinitionen. Det er indlagt i selve programmet. Det forlanger LINK-macroen, for den genererer adressen på parmen i A(PARM+X’80000000’). Hvis ikke jeg havde PARM med eller det var en konstant i programmet, så kunne jeg godt have brugt denne standard LINK i et reentrant program.


        STH   R3,PARMLGD              
***************************************
** FLYT VARIABEL LÆNGDE AF TEKST       
***************************************
        BCTR  R3,0                    
        EX    R3,MVC                  
        B     MVC+L'MVC               
MVC      MVC   PARMTXT(0),2(R2)        
PGM2     LINK  EP=PGM2,PARAM=PARM,VL=1                        
PGM2     DS    0H                                             
        CNOP  0,4                                            
        LA    1,IHB0011                         LIST ADDRESS
        B     IHB0011A                          BYPASS LIST  
IHB0011  EQU   *                                              
        DC    A(PARM+X'80000000')                            
IHB0011A EQU   *                                              
        CNOP  0,4                                            
        BAL   15,*+20            BRANCH AROUND CONSTANTS     
        DC    A(*+8)             ADDR. OF PARM. LIST         
        DC    A(0)                DCB ADDRESS PARAMETER      
        DC    CL8'PGM2'           EP PARAMETER               
        SVC   6                   ISSUE LINK SVC             
        B     RETURN                                         
PARM     DS    0F                                             
PARMLGD  DS    H                                              
PARMTXT  DS    CL120                                          

I stedet for at at bruge én standard LINK, skal du bruge to, - en LIST-form og en EXEC-form. LIST-formen beskriver konstanter og variable felter til LINK-kaldet. EXEC-formen udfører det faktiske LINK, akkurat som standard LINK. Det betyder, at du definerer din LIST-form sammen med dine andre konstanter og definerer et areal i dit Getmain’ede storage, hvor du kan flytte den op, inden du udfører EXEC-formen.
Macroparameteren MF=L fortæller, at du vil have lavet LIST-formen og MF=E, at du laver EXEC-formen. Læg mærke til, at i MF=E kommer navnet på feltet, hvor du flyttede LIST-formen til.
Det er måske lidt besværligt, men dit program bliver reentrant. Og det er smukt.
STORAGE   DSECT                                     
STORAGE_EYE_CATCHER DS CL16            EYE CATCHER
PARM      DS    0F                                  
PARMLGD   DS    H                                   
PARMTXT   DS    CL120                               
STOR_LGD EQU   *-STORAGE                           
PGM2_EXEC DS   XL(PGM2_LGD)
                      

        STH   R3,PARMLGD                 
******************************************
** FLYT VARIABEL LÆNGDE AF TEKST        **
******************************************
        BCTR  R3,0                       
        EX    R3,MVC                     
        B     MVC+L'MVC                  
MVC      MVC   PARMTXT(0),2(R2) 
******************************************                              
        MVC   PGM2_EXEC,PGM2_LIST                                      
PGM2     LINK  EP=PGM2,PARAM=PARM,VL=1,MF=(E,PGM2_EXEC)                 
PGM2     DS    0H                                                       
*                                                                 1ØL1D
*                                                                 1ØL1D
        LA    1,PGM2_EXEC                       LOAD PARAMETER REG 1   
        LA    14,PARM            PICKUP PARAMETER                      
        ST    14,0(0,1)                         STORE INTO PARAM. LIST
        OI    0(1),X'80'                 SET LAST WORD BIT ON ØG860P40
        CNOP  0,4                                                      
        BAL   15,*+20            BRANCH AROUND CONSTANTS               
        DC    A(*+8)             ADDR. OF PARM. LIST                   
        DC    A(0)                DCB ADDRESS PARAMETER                
        DC    CL8'PGM2'           EP PARAMETER                         
        SVC   6                   ISSUE LINK SVC              ØG381P2A
        B     RETURN                                                   
PGM2_LIST LINK EP=PGM2,SF=L                                             
        CNOP  0,4                                                      
PGM2_LIST DC   A(*+8)             ADDRESS OF EP PARAMETER               
        DC    A(0)           DCB ADDRESS PARAMETER                     
        DC    CL8'PGM2'      EP PARAMETER                              

PGM2_LGD EQU   *-PGM2_LIST                                              

Jeg ved ikke om du har lagt mærke til det, men der er en lille krølle i mit program, som jeg var nødt til at bruge for at kunne flytte parameteren, som kan have variabel længde. Det er den lille EX-kommando. Den tager den højrestillede byte i registeret og lægge det i anden byte af instruktionen, som den peger på, - her MVC. Det er en slags modificeringen af koden, men det er i CPU’en og IKKE i programmet. Jeg kunne også have brugt MVCL (Move Long), men det ville være for kedeligt og besværligt.