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