Page 1 of 1

IBM HLASM

PostPosted: Thu Jul 11, 2019 2:09 am
by Andyo2424
Hi, everyone I'm currently taking an assembly course (HLASM), I just had one question about explicit addressing D(X,B), How do I know what register to use as an index register? how do I know what value to input as a displacement value? how do I know what register to use as a base register? I often see examples like
5,8(0,2) but I dont understand what that goes or what that does, is it like an array? thank you

Re: IBM HLASM

PostPosted: Thu Jul 11, 2019 3:17 am
by Robert Sample
From the IBM Principles of Operation manual, which is the authoritative source for information about assembler and how the system works:
An operand address that refers to storage is derived
from an intermediate value, which either is contained
in a register designated by an R field in the instruction
or is calculated from the sum of three binary
numbers: base address, index, and displacement.
The base address (B) is a 64-bit number contained in
a general register specified by the program in a fourbit
field, called the B field, in the instruction. Base
addresses can be used as a means of independently
addressing each program and data area. In arraytype
calculations, it can designate the location of an
array, and, in record-type processing, it can identify
the record. The base address provides for addressing
the entire storage. The base address may also be
used for indexing.
The index (X) is a 64-bit number contained in a general
register designated by the program in a four-bit
field, called the X field, in the instruction. It is
included only in the address specified by the RX-,
RXE-, RXF-, and RXY-format instructions. The RX-,
RXE-, RXF-, and RXY-format instructions permit double
indexing; that is, the index can be used to provide
the address of an element within an array.
The displacement (D) is a 12-bit or 20-bit number
contained in a field, called the D field, in the instruction.
A 12-bit displacement is unsigned and provides
for relative addressing of up to 4,095 bytes beyond
the location designated by the base address. A 20-bit
displacement is signed and provides for relative
addressing of up to 524,287 bytes beyond the baseaddress
location or of up to 524,288 bytes before it.
In array-type calculations, the displacement can be
used to specify one of many items associated with an
element. In the processing of records, the displacement
can be used to identify items within a record.
A 12-bit displacement is in bit positions 20-31 of
instructions of certain formats (see Figure 5-1 on
page 5-4). In instructions of some formats, a second
12-bit displacement also is in the instruction, in bit
positions 36-47.
A 20-bit displacement is in instructions of only the
RSY, RXY, or SIY format. In these instructions, the D
5-10 z/Architecture Principles of Operation
field consists of a DL (low) field in bit positions 20-31
and of a DH (high) field in bit positions 32-39. When
the long-displacement facility is installed, the numeric
value of the displacement is formed by appending the
contents of the DH field on the left of the contents of
the DL field. When the long-displacement facility is
not installed, the numeric value of the displacement
is formed by appending eight zero bits on the left of
the contents of the DL field, and the contents of the
DH field are ignored.
In forming the intermediate sum, the base address
and index are treated as 64-bit binary integers. A
12-bit displacement is treated as a 12-bit unsigned
binary integer, and 52 zero bits are appended on the
left. A 20-bit displacement is treated as a 20-bit
signed binary integer, and 44 bits equal to the sign bit
are appended on the left. The three are added as
64-bit binary numbers, ignoring overflow. The sum is
always 64 bits long and is used as an intermediate
value to form the generated address. The bits of the
intermediate value are numbered 0-63.
A zero in any of the B1, B2, X2, B3, or B4 fields indicates
the absence of the corresponding address
component. For the absent component, a zero is
used in forming the intermediate sum, regardless of
the contents of general register 0. A displacement of
zero has no special significance.
Broadly, the base register may be your addressability register if you're accessing part of your CSECT, or you may have an instruction to set it: LA 3,VAR1 would load the address of VAR1 into register 3 and hence could be a base for further address manipulation. Which registers you use for base and index really depends upon your code.

Re: IBM HLASM

PostPosted: Thu Jul 11, 2019 4:52 am
by steve-myers
One more thing.

Queries regarding Assembler really belong in the Assembler area. Only queries about running IBM's HLASM belong in the JCL area, and your query is more about writing programs in Assembler.

These forums are more about responding to rather specific queries. We are not well equipped to write tutorials. This link points to an excellent text for Assembler programming. It's a PDF; you are probably better off retrieving the document and using a proper PDF file viewer to read the document than using the PDF viewer in most modern web browser programs. With patience you can find answers to your questions about base registers and index registers in this document.

Re: IBM HLASM

PostPosted: Thu Jul 11, 2019 2:58 pm
by NicC
Another thing - please learn to count! You said you had one question - I count four. There should be one question per topic. However, your questions are related to each other and could have been re-worded to ask just the one question about index registers in general and the specifics you wrote could have been written as examples of use that you were trying to understand.

Re: IBM HLASM

PostPosted: Fri Jul 12, 2019 5:21 pm
by steve-myers
Andyo2424 wrote:Hi, everyone I'm currently taking an assembly course (HLASM), I just had one question about explicit addressing D(X,B), How do I know what register to use as an index register? how do I know what value to input as a displacement value? how do I know what register to use as a base register? I often see examples like
5,8(0,2) but I dont understand what that goes or what that does, is it like an array? thank you

Yes, you're right. Taken in isolation, something like 5,8(0,2) is basically meaningless. In fact, most of us retired dinosaurs don't write it like that; we write 5,8(,2). It's the exact same thing, but it gets the pseudo index register 0 out of the picture as register 0 is not, and cannot be, an index register.

In fact, we might write

L 5,8(,2) or
ST 5,8(,2)

In some ways, in System/360 derived computer architectures, the term "index register" is basically meaningless. An earlier computer design - the IBM 704, which morphed over about 10 years to the 709, 7040 and 7090 computer systems - had several specialized registers called "index registers." These registers could only be used as index registers. By current standards they were weird as their values were subtracted, not added, to the basic operand address. The idea of an index register was considered to be important when the System/360 design was devised, but the idea of dedicated index registers was dropped. Instead an "index register" is just a general purpose register used as an "index register" in some instructions. In fact, for those of us dinosaurs changing over to System/360 from the 704 tradition the idea was sort of a sick joke as the ideas they were often used for in 704 type systems did not transition easily System/360. In fact, most of the time, in my opinion, you're better off thinking of the "index register" as the third operand in a 3 input adder. Just to show how elusive the concept is, it took me 20 years or more to realize this concept and put it into practice in my programs.

The index register idea went into instructions called "branch index high" or "branch index low or equal" which were analogs of 704 instructions with a similar name and purpose, but until you replaced the idea of "index" with the idea of "value" you could not realize the true worth of these instructions in System/360.

Re: IBM HLASM

PostPosted: Tue Jul 16, 2019 2:53 am
by steve-myers
Andyo2424 wrote:Hi, everyone I'm currently taking an assembly course (HLASM), I just had one question about explicit addressing D(X,B), How do I know what register to use as an index register? how do I know what value to input as a displacement value? how do I know what register to use as a base register? I often see examples like
5,8(0,2) but I dont understand what that goes or what that does, is it like an array? thank you

Now all this is a tutorial, which is not what these replies are supposed to be, but you asked for it!
  1. What register to use as an index register? You can use register 1 through 15 - the register that has the index value you need.
  2. What value to use as a displacement? It depends on the data; the question cannot be answered here. This program fragment is an example.
             USING IHADCB,5            ESATABLISH DCB DATA AREA ADDRESSING
             LA    5,ADCB              COMPUTE DCB ADDRESS
             MVC   RECFM,=CL8' '       INITIALIZE THE RECFM OUTPUT AREA
             LA    0,RTABN             LOAD ENTRIES IN RTAB
             LA    1,RTAB              COMPUTE ADDRESS OF RTAB
             LA    14,RECFM            COMPUTE ADDRESS OF RECFM OUTPUT AREA
    RECFM1   MVC   WKAREA,DCBRECFM     COPY BINARY RECFM TO A WORK AREA
             NC    WKAREA,0(1)         ISOLATE ATTRIBUTE BITS
             CLC   WKAREA,1(1)         ATTRIBUTE IN DCBRECFM?
             BNE   RECFM2              NO
             MVC   0(1,14),2(1)        COPY ATTRIBUTE TEXT TO OUTPUT
             LA    14,1(,14)           ADD 1 TO OUTPUT AREA POINTER
    RECFM2   LA    1,3(,1)             COMPUTE ADDRESS OF NEXT RTAB ENTRY
             BCT   0,RECFM1            CHECK IT
             DROP 5                    KILL DCB DATA AREA ADDRESSING
             ...
    RECFM    DC    CL5' '              RECFM TEXT
    WKAREA   DC    XL1'0'              WORK AREA
    ADCB     DCB   DSORG=PS,MACRF=PM,RECFM=VBA,LRECL=125  DEFINE A DCB
    *  RTAB - TABLE TO TRANSLATE DCBRECFM ATTRIBUTES TO TEXT
    *  OFFSET  PURPOSE
    *     0    ATTRIBUTE MASK
    *     1    ATTRIBUTE
    *     2    ATTRIBUTE TEXT
    RTAB     DC    AL1(DCBRECL,DCBRECF,C'F')
             DC    AL1(DCBRECL,DCBRECV,C'V')
             DC    AL1(DCBRECL,DCBRECU,C'U')
             DC    AL1(DCBRECBR,DCBRECBR,C'B')
             DC    AL1(DCBRECSB,DCBRECSB,C'S')
             DC    AL1(DCBRECTO,DCBRECTO,C'T')
             DC    AL1(DCBRECCC,DCBRECCA,C'A')
             DC    AL1(DCBRECCC,DCBRECCM,C'M')
    RTABN    EQU   (*-RTAB)/3
             ...
             DCBD  DEVD=DA,DSORG=PS
     

    The comments before the definition of the first RTAB entry describe the displacements.

    NC WKAREA,0(1)

    Displacement 0 in 0(1) can be readily deduced from the table. The displacement 0 in 0(1,14), where register 14 is an address in

    MVC 0(1,14),2(1)

    is pretty obvious. Displacement 2 in 2(1) is from the table.
  3. What register to use as a base register? Any register from 1 to 15 that is not being used for some other purpose. In this fragment, registers 1, 5 and 14 are being used as base registers. An unspecified register in the fragment is also being used as a base register to address symbols such as WKAREA, RTAB, RECFM and other symbols.
  4. Is it like an array? Yes and no. Perhaps like a C language (I presume you know C!) structure -
    struct rtab
     {
      unsigned char rtmask, rtattrb, rtattrtxt;
     } *reg;
A reasonable question is where do the symbols like DCBRECL, DCBRECF and the other DCBRECxx symbols come from? They are all defined in the DCBD IBM macro.
DCBRECL  EQU   DCBBIT0+DCBBIT1 -
*                             RECORD LENGTH INDICATOR
DCBRECF  EQU   DCBBIT0 -      FIXED RECORD LENGTH
DCBRECV  EQU   DCBBIT1 -      VARIABLE RECORD LENGTH
DCBRECU  EQU   DCBBIT0+DCBBIT1 -
*                             UNDEFINED RECORD LENGTH
This was copied from the OS/360 DCBD macro, which is not copyrighted, but they are identical to the values in the z/OS DFSMS DCBD macro. Similarly, the DCBBITx symbols are also defined in the DCBD macro.

Re: IBM HLASM

PostPosted: Tue Jul 16, 2019 4:06 am
by steve-myers
One more tutorial, with an example.
         LA    1,197               LOAD DAY OF YEAR FOR JULY 15 IN A  ->
                                    LEAP YEAR
         SR    14,14               LOAD MONTH OF YEAR
         IC    14,TAB1(1)           FOR DAY OF YEAR
         LR    15,14               COPY MONTH TO REG 15
         AR    14,14               MULTIPLY MONTH BY 2 IN REG 14
         AR    15,14               MULTIPLY MONTH BY 3 IN REG 15
         SH    1,TAB2(14)          COMPUTE DAY OF MONTH IN REG 1
         LA    15,TAB3(15)         COMPUTE ADDRESS OF ABBREVIATED     ->
                                    MONTH IN REG 15
         ....
TAB1     EQU   *-1
         DC    31AL1(1),29AL1(2),31AL1(3),30AL1(4),31AL1(5),30AL1(6)
         DC    31AL1(7),31AL1(8),30AL1(9),31AL1(10),30AL1(11),31AL1(12)
         DC    0Y(0)
TAB2     EQU   *-2
         DC    Y(0)                                 JAN
         DC    Y(31)                                FEB
         DC    Y(31+29)                             MAR
         DC    Y(31+29+31)                          APR
         DC    Y(31+29+31+30)                       MAY
         DC    Y(31+29+31+30+31)                    JUN
         DC    Y(31+29+31+30+31+30)                 JUL
         DC    Y(31+29+31+30+31+30+31)              AUG
         DC    Y(31+29+31+30+31+30+31+31)           SEP
         DC    Y(31+29+31+30+31+30+31+31+30)        OCT
         DC    Y(31+29+31+30+31+30+31+31+30+31)     NOV
         DC    Y(31+29+31+30+31+30+31+31+30+31+30)  DEC
TAB3     EQU   *-3
         DC    C'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'
In this example, we take day of year in register 1 and determine day of month (in register 1) and the address of the abbreviated month (in register 15). There are three tables: TAB1 is the month for each day of year, TAB2 is the day of year - 1 for for each month, and TAB3 is the abbreviated month names. The code fragment avoids doing a multiply instruction.

Now let's try to answer some obvious questions
  1. What is the reason for TABx EQU *-x? The index is a true value: day of year, for example is 1 through 366, so the first entry for day of year, 1, for example, has to be at TAB1 + 1.
  2. TAB1 is awfully big, isn't it? Yes. However, we want to show the use of an index register, so we need tables. The most common example that does not use indexing uses a different, but smaller table, but uses a loop. This code is faster and does not use a loop.
  3. Why use leap year day of year? Roughly 3 years in 4 are common years. Yes, but, as has been noted TAB1 is rather large. The equivalent table for a common year is almost as large. Better to have one large table than 2 large tables!