Page 1 of 1

Looking for Descriptive Sample Programs

PostPosted: Thu Jul 09, 2015 7:16 pm
by jcbrunelle13
Hi Everyone,

I very recently started learning z/os assembler, having some very limited experience with x86 in a college course. I've worked through the introductory course on IBM's site, which gave me a decent handle on different instructions, but did not give any descriptive examples of code.

I was wondering if anyone knew of any source of trivial programs that are well commented. I have searched for them extensively but have only come across either programs that are too complicated for me at my level or programs with little to no commentary. I'm trying to work up to the point where I can write a simple calculator program in assembler, as that's always been a good starting program to write.

Any help would be greatly appreciated.

Thanks,
jcbrunelle13

PS - I apologize if this topic has come up before, I didn't see any posts about it and couldn't find a search feature.

Re: Looking for Descriptive Sample Programs

PostPosted: Thu Jul 09, 2015 8:29 pm
by steve-myers
Actually, a "calculator" program, by which I think you mean something comparable to a 4 function (add / subtract / multiply / divide) program such as you see in very simple handheld devices and in many "flip" cell phones is more complex than you think. Even something like 123*456 to produce 56088 is easy enough to do in Assembler, but is still more complicated than you might think as it involves code to scan out substrings (123 and * and 456) which is more complicated to do in Assembler than you might think. At least you don't have to detect key presses and translate a key position to a value!

Re: Looking for Descriptive Sample Programs

PostPosted: Fri Jul 10, 2015 1:26 am
by jcbrunelle13
steve-myers,

Thanks for the reply. I guess I'm still trying to get in the mindset of assembly-level programming as opposed to high level languages. I'm getting more of a sense now how I over-simplified the calculator program. Thanks for the info! I did a little more searching through these forums and found someone link to www.simotime.com, which provides some good commented code. If you or anyone else thinks of any other resources for such a thing, please let me know.

Thanks again!
jcbrunelle13

Re: Looking for Descriptive Sample Programs

PostPosted: Fri Jul 10, 2015 5:14 pm
by steve-myers
This is too large to be easily understood, but it's a very limited calculator program.
***********************************************************************
*                                                                     *
* Title - CALC                                                        *
*                                                                     *
* Function / Operation - CALC is a very simple calculator program     *
*                                                                     *
* JCL -                                                               *
*   //        EXEC PGM=CALC                                           *
*   //SYSPRINT DD  SYSOUT=*                                           *
*   //SYSIN    DD  *                                                  *
*   50+30                                                             *
*                                                                     *
*   The data set specified by the SYSIN DD statement contains         *
*   calculator problems.  Each problem contains three fields          *
*   as shown in the example JCL.  The first and third fields          *
*   are 1 to 7 byte numbers.  The second field is a mathematical      *
*   function code: +, -, * /                                          *
*                                                                     *
* Status / Change Level -                                             *
*   V1L0 - July 2015                                                  *
*                                                                     *
***********************************************************************
CALC     CSECT                     Define program CSECT
         USING *,12                Establish program addressability
         SAVE  (14,12),,*          Save registers
         LR    12,15               Prepare program vase register
         LA    15,SAVEAREA         Compute address of the new save area
         ST    13,4(,15)           Add new save area to the
         ST    15,8(,13)            save area chain
         LR    13,15               Establish new save area pointer
         OPEN  (PRINT,OUTPUT,SYSIN,INPUT)  Open the data sets
NEXTCARD GET   SYSIN               Get a new input record
* Extract the two numbers and the operation from the input.  We use
* the TRT (TRanslate and Test) instruction to scan the input.  The
* name of the instruction is very poor: it does not "translate"
* anything.  The instruction works through an input string, from
* "left" to "right" one byte at a time.  It loads the byte into
* an internal register, uses the contents of the byte to compute
* the address of a "function byte" in a table that is addressed by
* the instruction.  If the "function byte" contains binary 0s, the
* instruction continues on to the nrxt byte.  If the "function byte"
* is not binary 0s, the instruction stores the address of the byte
* in register 1, the contents of the "function byte" in register 2,
* sets the condition code to non-zero, and terminates. If every
* input byte has function bytes that are binasry 0s, the instruction
* sets the condition code to 0 and terminates.  Now I do not know
* if my discussion is any more understandable than the discussion in
* Principles of Operation, but try working through a few input bytes
* yourself.
         LR    6,1                 Copy the record address to reg 6
         LR    3,1                 Copy the record aaddress to reg 3
         LA    4,71(,1)            Compute addr of end of data
         LR    15,4                Copy addr of end of data to reg 15
         SR    15,3                Compute length of data to scan
         SR    1,1                 Init reg 1
         SR    2,2                 Init reg 2
* The EX instruction directs the machine to run one instruction out
* of line.  The low order 8 bits of reg 15 are ORed with the second
* byte of the instruction, without changing the instruction in
* storage.  The instruction at TRT01 is a TRT instruction; the
* altered byte is length data.
         EX    15,TRT01            Scan for something interesting
         BZ    BAD                 Br if nothing interesting
* If the TRT instruction found a delinmiter in the TRTAB1 table, a
* non-numeric character, a +, -, *  or / character, or a blank,
* it stores the address of the data byte it found in reg 1, and the
* function code from the table in reg 2
         CHI   2,8                 Test function code
         BL    BAD                 Br if blank found
         CHI   2,20                Test if junk
         BH    BAD
         MVC   OPCODE,0(1)         Save the op code
         LA    5,1(,1)             Compute addr of next byte to scan
         SR    1,3                 Compute length of string
         BNP   BAD                 Oops, length must be > 0
         CHI   1,7                 Test if too long
         BH    BAD                 Yep
         BCTR  1,0                 Reduce length by 1
         EX    1,PACK01            Convert string from zoned decimal  ->
                                    to packed decimal
         LR    3,5                 Copy resume point to reg 3
         LR    15,4                Compute length to scan
         SR    15,3
         BCTR  15,0                Reduce length by 1
         LA    1,0(15,3)           Compute address of last byte in    ->
                                    the scan area
         EX    15,TRT01            Find the end of the string
         BZ    CNVT2               End of string
         CHI   2,4                 Found a blank?
         BNE   BAD                 No
CNVT2    SR    1,3                 Compute string length
         BNP   BAD                 Oops
         CHI   1,7                 Too long?
         BH    BAD                 Yep
         BCTR  1,0                 Reduce length by 1
         EX    1,PACK02            Convert zoned decimal to           ->
                                    packed decimal
         ZAP   RESULT,DATA1        Copy first string to RESULT
         CLI   OPCODE,C'+'         Br based on function
         BE    ADD
         CLI   OPCODE,C'-'
         BE    SUBTRACT
         CLI   OPCODE,C'*'
         BE    MULTIPLY
         CLI   OPCODE,C'/'
         BE    DIVIDE
BAD      PUT   PRINT,=CL80'THE FOLLOWING INPUT IS BAD'
         PUT   PRINT,(6)
         B     NEXTCARD
ADD      AP    RESULT,DATA2
         B     LISTRES
SUBTRACT SP    RESULT,DATA2
         B     LISTRES
MULTIPLY MP    RESULT,DATA2
         B     LISTRES
DIVIDE   ZAP   TEMP,RESULT
         DP    TEMP,DATA2
* The DP (Divide Decimal) instruction divides the output area into 2
* fields: the quotient and the remainder
         ZAP   RESULT,TEMP(L'TEMP-L'DATA2)  Copy the result in TEMP   ->
                                             to RESULT
LISTRES  MVI   OUTLINE,C' '        Clear the output line
         MVC   OUTLINE+1(L'OUTLINE-1),OUTLINE
         LA    14,OUTLINE          Load start of output line
         ZAP   TEMP,DATA1          Copy the first number to TEMP
         BAL   11,CNVTTEMP         Convert TEMP to decimal digits in  ->
                                    the output line
         MVC   0(3,14),=CL3' '     Add 3 blanks to the output line
         MVC   1(1,14),OPCODE      Copy the operation code to the     ->
                                    3 blanks
         AHI   14,3                Add 3 to reg 14
         ZAP   TEMP,DATA2          Convert DATA2 to decimal in the
         BAL   11,CNVTTEMP          output line
         MVC   0(3,14),=CL3' '     Add 3 blanks to the output line
         MVI   1(14),C'='          Insert an = into the 3 blanks
         AHI   14,3                Add 3 to reg 14
         ZAP   TEMP,RESULT         Convert the result to decimal
         BAL   11,CNVTTEMP
         PUT   PRINT,OUTLINE       Print the line
         B     NEXTCARD
EOF      CLOSE (PRINT,,SYSIN)      Close the data sets
         L     13,4(,13)           Load address of the higher save area
         RETURN (14,12),T,RC=0     Restore registers and return
         EJECT
* Convert the contents of TEMP to decimal digits
CNVTTEMP MVC   CVWORK,EDPATT        output line
         LA    1,CVWORK+L'CVWORK-1 Compute address of the last byte   ->
                                    in CVWORK
         EDMK  CVWORK,TEMP         Prepare the digits
         CP    TEMP,=P'0'          Compare TEMP with 0
         BNM   SIGNOK              Br if TEMP >= 0
         BCTR  1,0                 Insert a floating - before the first
         MVI   0(1),C'-'            significant digit
SIGNOK   LR    0,1                 Copy address of the first          ->
                                    significant digit to reg 0
         LA    1,CVWORK+L'CVWORK   Compute address of the end of CVWORK
         SR    1,0                 Compute length of the digits       ->
                                    in CVWORK
         LR    15,1                Copy the length to reg 15
* The MVCL instruction copies data
*   Reg 14 - Address of start of output area
*   Reg 15 - Expected data length in output area
*   Reg  0 - Address of start of input area
*   Reg  1 - Data length in input area
* As the instruction executes, the contents of the registers are
* updated, so when the MVCL completes reg 14 points to the byte after
* the copied data.
         MVCL  14,0
         BR    11                  Return
         SPACE 2
* The following instructions are objects of an EX instruction.
* Data areas within the instruction coded as *-* are effectively
* replaced by data in a register by the EX instruction; *-* is a
* loose convention to indicate the data area is modifed.
TRT01    TRT   0(*-*,3),TRTAB1
PACK01   PACK  DATA1,0(*-*,3)
PACK02   PACK  DATA2,0(*-*,3)
SAVEAREA DC    9D'0'               72 byte OS/350 save area
TRTAB1   DC    0XL256'0',256AL1(24)  Table used by the TRT instruction.
         ORG   TRTAB1+C' '           Most of the table is set to 24, to
         DC    AL1(4)                indicate an invalid character.
         ORG   TRTAB1+C'+'           Other characters are set to other
         DC    AL1(8)                values
         ORG   TRTAB1+C'-'
         DC    AL1(12)
         ORG   TRTAB1+C'*'
         DC    AL1(16)
         ORG   TRTAB1+C'/'
         DC    AL1(20)
         ORG   TRTAB1+C'0'
         DC    10AL1(0)
         ORG   ,
PRINT    DCB   DSORG=PS,MACRF=PM,DDNAME=SYSPRINT,RECFM=FB,LRECL=80
SYSIN    DCB   DSORG=PS,MACRF=GL,DDNAME=SYSIN,EODAD=EOF
* "Pattern" for the ED and EDMK instructions.
* X'20' and X'21' bytes are called "digit select" characters and are
* replaced by decimal digits from packed decimal data that is the
* source data for an ED or EDMK instruction.  When preparing these
* patterns, be careful to code one digit select for each decimal digit
* in the input data.  In this program the input data is a 8 byte
* data area containing 15 packed decimal digits, so the pattern
* contains 15 digit select chasracters.
EDPATT   DC    0C' NNN,NNN,NNN,NNN,NNN'
         DC    C' ',3X'20',C',',3X'20',C',',3X'20',C',',3X'20',C',',X'2>
               02120'
CVWORK   DC    CL(L'EDPATT)' '
DATA1    DC    PL4'0'
DATA2    DC    PL4'0'
RESULT   DC    PL8'0'
TEMP     DC    PL8'0'
OPCODE   DC    C' '
OUTLINE  DC    CL80' '
         DC    0D'0'
         LTORG ,
         END   CALC
This JCL -
//        EXEC PGM=CALC                       
//STEPLIB  DD  DISP=SHR,DSN=&SYSUID..CALC.LOAD
//SYSPRINT DD  SYSOUT=*                       
//SYSIN    DD  *                             
25013+55                                     
25013-13150                                   
13150-25013
produced this output
25,013 + 55 = 25,068     
25,013 - 13,150 = 11,863
13,150 - 25,013 = -11,863

Re: Looking for Descriptive Sample Programs

PostPosted: Thu Jul 16, 2015 8:02 pm
by jcbrunelle13
Thanks a ton!

This is all very well explained and has helped a lot with my understanding of some of the basics. I'm still working through some things that I don't understand quite yet but your program certainly helps, as does some of the other samples on this forum.

Much appreciated!

-jcbrunelle13

Re: Looking for Descriptive Sample Programs

PostPosted: Fri Jul 17, 2015 5:14 am
by steve-myers
If there is something you don't understand in the program, try to formulate a question about it and ask away.

The register usage in the code that builds the output line was designed to facilitate the use of the MVCL instruction.

Reg 14 has the address of the current position in the output line. reg 15 is available for a length.

However, it's dispersed over larger code, so it's hard to understand what's going on. For example -
         LA    14,OUTPUT
         MVC   PATTERN,MASTER
         LA    1,PATTERN+L'PATTERN-1
         EDMK  PATTERN,VALUE
         LR    0,1
         LA    1,PATTERN+L'PATTERN
         SR    1,0
         LR    15,1
         MVCL  14,0
         ...
MASTER   DC    0C' NNNNN',C' ',X'2020202120'
PATTERN  DC    CL(L'PATTERN)' '
VALUE    DC    P'12345'
OUTPUT   DC    CL80' '
The code keys on 2 instructions: EDMK and MVCL. The ED and EDMK instructions convert packed decimal digits to printable digits under control of a pattern. The difference is EDMK usually sets register 1 as the address of the first non-zero digit and ED does not alter any register.

The code starts by setting reg 14 to the start of the output area -

LA 14,OUTPUT

Next we prepare an edited number.

MVC PATTERN,MASTER
LA 1,PATTERN+L'PATTERN-1
EDMK PATTERN,VALUE

The ED and EDMK instructions use a pattern, but they destroy the pattern in their operation. The MVC instruction copies the master pattern to the EDMK instruction's output area.

Left alone, ED and EDMK produce a right justified number in the output area. In other words, with the pattern we're using, if the value is P'00123', after the EDMK executes, the pattern area will contain bbb123, where b is a blank, and register 1 will point to the 1. The contents of PATTERN is OK for a tabular report where we are producing columns of numbers, but it's not so good for a message, where we want just the numbers with no excess blanks

We do not want the leading blanks in our final output.

LR 0,1
LA 1,PATTERN+L'PATTERN
SR 1,0
LR 15,1
MVCL 14,0

First, we copy the address of the 1 in register 1 to register 0. We do this for 2 reasons. First we save the start of the number for the MVCL instruction and we need register 1 to be a length register for the MVCL instruction. Next, we compute the length. The LA instruction computes the address of the end of the pattern area, and the SR instruction computes the length of the data. At this point registers 14, 0 and 1 are ready for the MVCL instruction, but register 15 needs a length: the LR instruction copies the length from register 1 to register 15. Now perhaps you're thinking 2 lengths? Isn't this over kill? Well, yes, for our purposes it is, but the MVCL instruction can do more, which we're not doing, so setting the 2 length registers to the same value is necessary.

Finally, the MVCL copies the 123 to the output area, but it also updates register 14 to point to the byte after the 123.

There are other ways to accomplish this. The original System/360 did not have the MVCL instruction, so we would do something like this -
         LA    14,OUTPUT
         MVC   PATTERN,MASTER
         LA    1,PATTERN+L'PATTERN-1
         EDMK  PATTERN,VALUE
         LA    15,PATTERN+L'PATTERN
         SR    15,1
         BCTR  15,0
         EX    15,MVC
         LA    14,1(15,14)
         ...
MVC      MVC   0(*-*,14),0(1)
In this code fragment, just register 15 is being used for the length. The BCTR instruction reduces the value in register 15 by 1 because the length in an instruction like MVC is 1 less than actual length. In other words, to copy 3 bytes, the length value in the instruction is 2. Since we're dealing with short lengths, this will work.
         SR    15,1
         EX    15,MVC
         AR    14,15
         ...
MVC      MVC   0(*-*,14),0(1)
The MVC will copy 1 extra byte to the output area, but register 14 will be OK.