Notes on IBM Mainframe Assembly Language Kevin C. O'Kane Last update: March 8, 2007
On-Line IBM S/390 Principles of Operation
PC Based Simulator for IBM 370 (PC370.ZIP)
Note: the author of the simulator, Donald S. Higgins, no longer accepts registrations and states that you may freely distribute the shareware version without charge.
AR R2,R3
*Contents of R3 added to R2,
result remains in R2
SR R3,R4 *Contents of R4 subtracted from R3,
result in R3
LR R4,R5 *Contents of R5 copyed to R4
OI MEM1,X'0F' *a byte containing X0F is OR'ed with the byte in memory at MEM1
A R5,0(R0,R8) *the word in memory pointed to by R8 is added to R5
A R5,20(R0,R8) *the word in memory 20 bytes past the address in R8 is added to R5
A R5,20(R8,R0) *same as above
A R5,20(R0,R0) *the word at location 20 is added to R5
A R5,20(R7,R8) *the word 20 bytes past the sum of R7 and R8 is added to R5
LA R5,20(R7,R8) *the address is calculated and placed in R5
LA R5,4(R0,R5) *the value in R5 is incremented by 4
A R5,MEM2 *the word at memory location labeled MEM2 is added to R5.
A R5,MEM2+4 *the word 4 bytes past MEM2 is added to R5
A R5,MEM2(R7) *the word at MEM2 + R7 is added to R5
The last three examples assume you have established a base register and that MEM2 is a label in the data area of your program.
MVC 0(30,R6),0(R7) *30 bytes in memory beginning at the address in R7 are copied
*to memory the address beginning at the address in R6
MVC 20(30,R6),50(R7) *30 bytes in memory beginning at 50 bytes past the address
*in R7 are copied to memory beginning at 20 bytes past the
*address in R6
MVC MEM1,MEM2 *the bytes beginning at label MEM2 are copied to the memory beginning
*at MEM1. Assumes a base register exists and the MEM1 and MEM2
*are labels with length attributes. The length code is determined by
*the length attribute of the target.
Programming
PRINT NOGEN
BEGIN BEGIN
REGS
The PRINT NOGEN is a directive to the assembler and tells it to print your expanded code. The BEGIN macro with the label BEGIN established the linkage and sets up R13 as your base register (an unusual choice). It also names your control section BEGIN (from the label - it does not need to be BEGIN - use any name up to 8 characters beginning with a letter and containing letters and numbers). The REGS macro makes it possible to use R0, R1, R2, ... rather than 0, 1, 2, ... which would be required otherwise.
To return and restore the calling program's registers, use the RETURN macro. The very end of the file has an END directive with the name of the control section.
Example of a program to sum the integers from 0 to 10:
PRINT NOGEN
BEGIN BEGIN
REGS
SR R2,R2 * zero R2
SR R3,R3 * zero R3
LOOP AR R2,R3
LA R3,1(R0,R3) * increment R3
C R3,=F'10'
BNE LOOP
CVD R2,DBL * converts from binary to packed
ED RESULT,DBL+6 * converts from packed to zoned
WTO RESULT
RETURN
LTORG
RESULT DC X'40202120'
DBL DC D'0'
END BEGIN
|
The program zero's out R2 and R3. It adds R3 to R2 and increments R3. It tests R3 against the value 10 and branches back up to LOOP if not equal. Whne R3 equals 10, it falls through. Printing the contents of a register involve converting the binary contents of the register (R3) to packed decimal (CVD) then unpacking the reslult to zoned decimal (printable). The unpacking is done by the ED instruction. The WTO macro prints the value in the memory locations associated with the label RESULT.
These instructions branch depending on settings in the condition code. The condition code can range in value from 0 to 3. It is set after many instructions to indicate the result (negative, zero, positive, overflow, for example, after binary arithmetic instructions). In both the BC and BCR, RX and RR instructions, respectively, the first operand is treated as a mask rather than as a register designation. The mask is thus 4 bits. Each bit corresponds to a condition code value for which the instruction will branch. If mask bit one is 1, the instruction will branch if the condition code is zero, if mask bit two is 1, the instruction will branch if the condition code is 1, mask bit three for a condition code of 2, and mask bit four for condition code of 3. Thus is bits 0 and 2 of the mask are 1, the instruction will branch if the condition code is either 0 or 2. If all bits of the mask are zero, no branch ever takes place. If all bits of the mask are 1, a branch always takes place (called an unconditional branch).
The mask can be specified in any manner. The most popular are as a decimal number or as a bit string. As a bit string, the bits are set by position to indicate the branch. If specified as a decimal, the decimal number is the equivalent of the bit string. Examples:
BC B"1000",LAB or BC 8,LAB Branch if condition code is zero BC B"0100",LAB or BC 4,LAB Branch if condition code is one BC B"0010",LAB or BC 2,LAB Branch if condition code is two BC B"0001",LAB or BC 1,LAB Branch if condition code is three BC B"1001",LAB or BC 9,LAB Branch if condition code is three or zero BC B"1011",LAB or BC 11,LAB Branch if condition code is three, two or zero |
Additionally, there are builtin extended mnemonic branch instructions. These are instructions where the assmbler will fill in the mask for you. See the instruction list for details.
Note: in the BC instruction, the branch address is computer in the usual way for an RX instruction. For the BCR instruction, the branch address is the contents of the register specified as the second operand except, if the second operand is specified as register zero, no branch takes place.
* Signed arithmetic
C R3,LAB *artihmetic full word binary compare
CR R3,R4 *arithmetic full word binary compare
CH R3,LAB *arithmetic half word compare
CP LAB1,LAB2 *signed packed decimal compare
* condition code: A = B 1000
* A < B 0100
* B > C 0010
* Unsigned logical compare
CL R3,LAB *unsigned full word binary compare
CLR R3,R4 *unsigned full word compare
CLC LAB1,LAB2 *unsigned string comparison
CLI LAB,C'X' *unsigned one byte comparison
* condition code: A = B 1000
* A > B 0100
* A < B 0010
|
The BAL and BALR instructions unconditionally (i.e., they always branch - they do not depend on the condition code) branch to the address specified by the second operand (a base, index, displacement address in the case of the BAL and the address contained in the register designated as the second operand in the case of the BALR [except if the register specified is R0, in which case no branch takes place]). In both cases, the abosolute memory address of the instruction following the BAL or BALR is placed into the register specified as the first operand.
An important use for these instructions is to branch to a subroutine and load into a register the address of the return point. In the case of the BALR, it is often used, in combination with R0 as the second operand, to load a register with the absolute memory address of the byte following the instruction. Example:
L R15,=V(SUB1) * load the address of a subroutine
BALR R14,R15 * branch to subroutine
|
The IBM mainframe has a data type called packed decimal. In this format, decimal numbers are represented as a sequence of 1 to 16 bytes, with two decimal digits to the byte except for the last byte which has one digit and a sign. Thus, numbers from 1 to 31 digits can be respresented. Each digit is stored in 4 bits - half a byte. The final byte has its low order 4 bits as the sign of the number. The hex digits C, A, F, and E indicate the number is positive while D and B indicate a negative number.
A printable number is said to be in zoned format. In zoned format, the high oreder 4 bits of each byte are all ones (hex F) and the low order 4 bits are the digit portion.
The instruction CVD converts a binary quantity in a register to packed decimal; the instruction CVB converts a packed decimal to binary. The ED (edit) instruction converts from packed decimal to zoned decimal and the PACK instruction converts from zoned decimal to packed decimal. The CVD is unusual in that the target is addressed by the second operand.
A DC statement reserves and initializes memory in your program. The DS statement reserves memory without initialization. There are a number of format variations:
LAB01 DC F'123' *binary full word LAB2 DC C'HELLO WORLD' *character string LAB3 DC B'1011101010001001' *bit string LAB4 DC X'2F3C' *hexadecimal string LAB5 DC P'1234' *packed decimal string LAB6 DS 18F *reserve 18 full words |
You may use a shorthand notation in place of a label for the source memory operand in many instructions. A literal looks like a DC operand but is preceeded by an "=" sign. Note: Immediate operands are not literals, they are a single byte value. Examples:
L R1,=F'123' *loads R1 with 123
MVC MESSAGE,=C'Hello World' *moves the string to MESSAGE
MVC RESULT,=X'40202120' *moves an edit pattern to RESULT
CLI LAB,C'X' *immediate - no = sign
|
Literals become DC's and placed in your program immediately after the LTORG directive.
Memory operands in RX, SI, SS and RS instructions are addressed as a combination of index register, base register and displacement (RX), or displacement and base (all others). Even in the case of RX instructions, the index register is seldom used and addressing of the memory operand is accomplished mainly by base and displacement.
When addressing a memory operand with base and displacement, the base register (any register between R1 and R15 but usually R12 or lower) contains the absolute address of a location in memory. The memory operand is calculated as a forward displacement from the location in memory pointed to by the base register. Displacements are positive 12 bit numbers and thus can range from 0 to 4095. An assembly language program loads its base register at the beginning and the assmebler, having been told which register is the base and where it is pointing, calculates the displacements for symbolic labels used in the program.
The purpose of base-displacement addressing was to permit code modules to be relocatable to any place in real memory. In order for that to happen, program modules need to address operands without using absolute addresses. Instead, addresses are relative to the contents of a base register. If a module is loaded to another area of memory, so long as the base registers are adjusted, the operands of the program are still at the same relative displacement from the base. (Note: most programs have a few absolute addresses that are adjusted for the load point during actual program load.)
One problem with base-displacement addressing is that the maximum distance from a base register is 4095 bytes. This is solved by having multiple base registers with the second pointing 4096 bytes beyond the first and so forth. However, for large programs, there are not enough spare registers so other techniques are employed. In larger programs, blocks of code establish their own base register on entry so the same register or registers are re-used. Loading a base register with the an absolute addres can be achieved by a BALR instruction with the second operand being R0. No branch takes place but the first operand receieves the absolute address of the byte immediately following the BALR:
BALR R12,R0
USING *,R12
|
The above loads the absolute address of the byte following the BALR into R12 then tells the assmebler to use R12 as a base register. You will also note the DROP directive. This discontinues use of a base register. The use of USING and DROP are assemble-time directives - they cover areas of code and are not run time states.
When operands can be addressed with a valid base and displacement combination, they are said to be 'in using'; if an operand is beyond the 4095 byte displacement of a base register, it is said to be 'out of using'.
The following is often seen if more than one base register is being set:
BALR R12,R0
USING *,R12,R11,R10
LA R11,2048(R0,R12)
LA R11,2048(R0,R11)
LA R10,2048(R0,R11)
LA R10,2048(R0,R10
|
This loads R12 with the absolute address of the byte imeediately beyond the BALR. Then it tells the assmebler that registers 12, 11 and 10 maybe used for addressing. The assembler assumes that these registers are set to 4096 and 8192 bytes apart, respectively. Then, the LA instruction is used to set R11 and R10 from the value in R12. Note: the maximum displacement is 4095 so two LA's are required to add 4096.
For example, take the program:
PRINT NOGEN
BEGIN BEGIN
REGS
SR R2,R2 * zero R2
SR R3,R3 * zero R3
LOOP AR R2,R3
LA R3,1(R0,R3) * increment R3
C R3,=F'10'
BNE LOOP
CVD R2,DBL * converts from binary to packed
ED RESULT,DBL+6 * converts from packed to zoned
WTO RESULT
RETURN
LTORG
RESULT DC X'40202120'
DBL DC D'0'
END BEGIN
|
This program ostensibly makes use of four symbolic references whose base/displacement must be calculated by the assembler. These are: LOOP, RESULT, DBL and =F'10'. Additionally, there are several other symbolic references generated by the macros (BEGIN, REGS, WTO and RETURN). If you assemble the above and look at the listing file (the .PRN file from the simulator), you see:
SUM PAGE 1
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
000000 1
000000 2 PRINT NOGEN
000000 3 *++++ BEGIN
000000 4 BEGIN CSECT
000000 5 USING *,15
000000 47F0F058 0058 6 B KZHQX001
000004 0B 7 DC AL1(11)
000005 C2C5C7C9D5404040 8 DC CL11'BEGIN '
000010 0000000000000000 9 HZQKX001 DC 18F'0'
000058 90ECD00C 000C 10 KZHQX001 STM 14,12,12(13)
00005C 50D0F014 0014 11 ST 13,HZQKX001+4
000060 18ED 12 LR 14,13
000062 41D0F010 0010 13 LA 13,HZQKX001
000066 50D0E008 0008 14 ST 13,8(0,14)
00006A 15 DROP 15
00006A 16 USING HZQKX001,13
00006A 17 *+++++++ REGS
00006A 00000000 18 R0 EQU 0
00006A 00000001 19 R1 EQU 1
00006A 00000002 20 R2 EQU 2
00006A 00000003 21 R3 EQU 3
00006A 00000004 22 R4 EQU 4
00006A 00000005 23 R5 EQU 5
00006A 00000006 24 R6 EQU 6
00006A 00000007 25 R7 EQU 7
00006A 00000008 26 R8 EQU 8
00006A 00000009 27 R9 EQU 9
00006A 0000000A 28 R10 EQU 10
00006A 0000000B 29 R11 EQU 11
00006A 0000000C 30 R12 EQU 12
00006A 0000000D 31 R13 EQU 13
00006A 0000000E 32 R14 EQU 14
00006A 0000000F 33 R15 EQU 15
00006A 1B22 34 SR R2,R2 * zero R2
00006C 1B33 35 SR R3,R3 * zero R3
00006E 1A23 36 LOOP AR R2,R3
000070 41303001 0001 37 LA R3,1(R0,R3) * increment R3
000074 5930D09C 00AC 38 C R3,=F'10'
000078 4770D05E 006E 39 BNE LOOP
00007C 4E20D0A8 00B8 40 CVD R2,DBL
000080 D203D0A4D098 00B4 00A8 41 MVC RESULT,=X'40202120'
000086 DE03D0A4D0AE 00B4 00BE 42 ED RESULT,DBL+6
00008C 43 *+++++++ WTO RESULT
00008C 4300D0A8 00B8 44 IC 0,RESULT+L'RESULT
000090 925BD0A8 00B8 45 MVI RESULT+L'RESULT,C'$'
000094 4120D0A4 00B4 46 LA 2,RESULT
000098 0AD1 47 SVC 209
00009A 4200D0A8 00B8 48 STC 0,RESULT+L'RESULT
00009E 49 *+++++++ RETURN
00009E 58DD0004 0004 50 L 13,4(13)
0000A2 98ECD00C 000C 51 LM 14,12,12(13)
SUM PAGE 2
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
0000A6 07FE 52 BR 14
0000A8 53 LTORG
0000A8 40202120 53 X'40202120'
0000AC 0000000A 53 F'10'
0000B0 0005 54 FIVE DC H'5'
0000B2 0003 55 THREE DC H'3'
0000B4 40202120 56 RESULT DC X'40202120'
0000B8 4000000000000000 57 DBL DC D'0'
0000C0 58 END BEGIN
SUM PAGE 3
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
SYMBOL VALUE LENGTH TYPE ID DEF# XREF#
BEGIN 00000000 000000C0 CST 01 00004 00058
DBL 000000B8 00000008 REL 01 00057 00042 00040
FIVE 000000B0 00000002 REL 01 00054
HZQKX001 00000010 00000004 REL 01 00009 00016 00013 00011
KZHQX001 00000058 00000004 REL 01 00010 00006
LOOP 0000006E 00000002 REL 01 00036 00039
R0 00000000 00000001 ABS 00 00018 00037
R1 00000001 00000001 ABS 00 00019
R10 0000000A 00000001 ABS 00 00028
R11 0000000B 00000001 ABS 00 00029
R12 0000000C 00000001 ABS 00 00030
R13 0000000D 00000001 ABS 00 00031
R14 0000000E 00000001 ABS 00 00032
R15 0000000F 00000001 ABS 00 00033
R2 00000002 00000001 ABS 00 00020 00040 00036 00034 00034 00040
R3 00000003 00000001 ABS 00 00021 00038 00037 00037 00036 00035
00035 00038 00037
R4 00000004 00000001 ABS 00 00022
R5 00000005 00000001 ABS 00 00023
R6 00000006 00000001 ABS 00 00024
R7 00000007 00000001 ABS 00 00025
R8 00000008 00000001 ABS 00 00026
R9 00000009 00000001 ABS 00 00027
RESULT 000000B4 00000004 REL 01 00056 00048 00048 00046 00045 00045
00044 00044 00042 00041
THREE 000000B2 00000002 REL 01 00055
. SUM PAGE 4
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
LITERAL CROSS REFERENCE
0000A8 58 X'40202120'
0000A8 58 00041
0000AC 58 F'10'
0000AC 58 00038
|
Notes on the above:
Why is R15 used as a base register and why is it pointing at the beginning of your program? Because on entry into a program, R15 always points at the first instruction of the program. At assembly time, we normally list the addresses of the program beginning as location counter value 000000. However, when the program runs, it will be located at some other address, let us say 100000. In that case, R15 will have 100000 in it but the label we are branching to will still be X058 bytes away.
Input/output operations on a mainframe were traditionally record oriented - usually involving fixed length records. Both input and output operations first require that you create a DCB - Data Control Block - a macro that creates a table that the system uses to communicate with the file or device. A DCB has many possible optional parameters, only a few of which are shown here.
In the following example, input is read from a file named INPUT.DAT and written to the console (standadr out, on a PC). The input DCB is named INDCB (see below) and the parameters to in mean the following:
LRECL=32 logical record length of 32 bytes RECFM=F fixed length records MACRF=G the GET macro will be used to access the file EODAD=ATEND branch to label ATEND on end of data DDNAME=INPUT.DAT file name to be opened and read |
Note that the continuation of the DCB begins in exactly column 16. Note also, that no line may extend past column 71.
The program begins as usual. The OI instruction sets a flag in the DCB requesting conversion from ASCII to EBCDIC. This is not needed on an actual mainframe. The OPEN macro invokes the operating system and tells it to open the file named in INDCB. The GET macro causes input records to be read from the file and placed in REC. The GET macro always specifies the DCB associated with the file being read. The WTO writes out the record and the branch (unconditional) loops. The loop terminates when an end of file is reached at which time control is passed to the label ATEND and the file is closed and the program terminates.
The input file INPUT.DAT looks like:
123456789012345678901234567890 test 1 ....................... test 2 ....................... test 3 ....................... |
Note that each line is exactly 30 bytes long. However, 32 bytes are actually read. This is because, on a Windows PC, carriage-return and line-feed (CR/LF) are appended to the end of every line. This will be obvious when you write the records. Each will have a blank line after it because of the CR/LF in the record and because the WTO also writes a CRLF after each record it prints.
PRINT NOGEN
START 0
REGS
BEGIN BEGIN
OI INDCB+10,X'08' convert ASCII to EBCDIC
OPEN INDCB
LOOP GET INDCB,REC read a record
WTO REC write the record
B LOOP loop
*
* EOJ processing
*
ATEND CLOSE INDCB
RETURN
*
* Literals
*
LTORG
*
* File DCB's
*
INDCB DCB LRECL=32,RECFM=F,MACRF=G,EODAD=ATEND,
DDNAME='INPUT.DAT'
*
* input record
*
REC DS CL32
END BEGIN
C:\asmdisk\min>asm IOEX1
C:\asmdisk\min>del report.txt
Could Not Find C:\asmdisk\min\report.txt
C:\asmdisk\min>m370 IOEX1
C:\asmdisk\min>a370 IOEX1/lx
***********************************************
* PC/370 System Release 4.2 01/07/88 *
* Copyright (C) 1988 Donald S. Higgins *
* *
* You are encouraged to copy and share this *
* package with other users on the condition *
* the package is not distributed in modified *
* form, and that no fee is charged. If you *
* find PC/370 useful, send 45 dollars to the *
* address below to become registered user and *
* support continued shareware development. *
* Registered users will receive notices of *
* future PC/370 releases. *
* *
* Don Higgins *
* 6365 - 32 Avenue, North *
* St. Petersburg, Florida 33710 *
***********************************************
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
STATS SYM=00025 MAXSTD=00005 LIT=00000 MAXLTD=00000 BTMEM=51764
NO ERRORS FOUND
C:\asmdisk\min>l370 IOEX1/lx
***********************************************
* PC/370 System Release 4.2 01/07/88 *
* Copyright (C) 1988 Donald S. Higgins *
* *
* You are encouraged to copy and share this *
* package with other users on the condition *
* the package is not distributed in modified *
* form, and that no fee is charged. If you *
* find PC/370 useful, send 45 dollars to the *
* address below to become registered user and *
* support continued shareware development. *
* Registered users will receive notices of *
* future PC/370 releases. *
* *
* Don Higgins *
* 6365 - 32 Avenue, North *
* St. Petersburg, Florida 33710 *
***********************************************
PC/370 LINKAGE EDITOR OPTIONS ON = LXEFIP
STATS SYM=00002 MAXSTD=00001 BTMEM=57752
NO ERRORS FOUND
C:\asmdisk\min>IOEX1
123456789012345678901234567890
test 1 .......................
test 2 .......................
test 3 .......................
C:\asmdisk\min>pause
Press any key to continue . . .
|
Output is handled similarly:
PRINT NOGEN
START 0
REGS
BEGIN BEGIN
OI INDCB+10,X'08' convert ASCII to EBCDIC
OI OUTDCB+10,X'08' convert EBCDIC to ASCII
OPEN INDCB
OPEN OUTDCB
LOOP GET INDCB,REC read a record
PUT OUTDCB,REC write the record
B LOOP loop
*
* EOJ processing
*
ATEND CLOSE INDCB
CLOSE OUTDCB
RETURN
*
* Literals
*
LTORG
*
* File DCB's
*
INDCB DCB LRECL=32,RECFM=F,MACRF=G,EODAD=ATEND,
DDNAME='INPUT.DAT'
OUTDCB DCB LRECL=32,RECFM=F,MACRF=P,DDNAME='OUT.DAT'
*
* input record
*
REC DS CL32
END BEGIN
|
The output file OUT.DAT is identical to the input file (PUT does not add CR/LF's)
Arithmetic
Arithmetic on an IBM mainframe can be carried out in binary integer mode, packed decimal mode and floating point. Flointing point is not covbered here.
When numbers are read from character (EBCDIC) input, they are in Zoned Decimal format. For example, the number 1234 in EBCDIC appears as:
F1 F2 F3 F4 (Hex)
Arithmetic may not be performed on these character representations of numbers. Instead, they must be converted to one of the numeric types, such as Packed Decimal or Integer (binary).
A Packed Decimal is a string of bytes containing in each half byte a value (in bits) from 0 to 9 except for the last half byte. The last half byte contains the sign of the number. The hex codes C,A,F, and E mean the number is positive and the codes D and B mean its negative. Thus, the above Zoned Decimal number, in packed format would be:
01 23 4F (Hex)
In this format, it can be seen that the zones have been eliminated and a sign appended.
Packed Decimal numbers can occupy up to 16 bytes and thus can represent numbers up to 31 digits in length. Packed Decimal is especially useful for business applications where many digits of accuracy are required. Packed Decimal operations do not involved round-off errors that are common with floating point numbers.
Use the PACK instruction to convert a positive Zoned Decimal number to Packed Decimal. The PACK instruction removes the zones and packs the numerics except for the last byte where the zone and numeric are swapped. Since the zone of a text number is F, all numbers appear to be positive (sign of F). To change the sign, modify the numeric field of the last bytes with something like a MVN (Move Numerics). The PACK instruction packs into the first operand from the second. Each operand may be up to 16 bytes in length.
Once a number is in packed format, you may do arithmetic on it. While packed (called decimal) arithmetic is slower thatn binary arithmetic, it can handle more digits of accuracy and it does not need any further conversion. To read in a number and convert it to binary, you first must pack the number (PACK is very fast), then perform a CVB (convert to binary) which converts the packed number to binary leaving the result in a register. The CVB is non-trivial. For many commercial transactions where a record is read and updated (by adding or subtracting) then written back to disk, packed arithmetic is faster and more flexible.
The most simple packed instructions are AP (Add Packed), SP (Subtract Packed), and CP (Compared Packed). The following illustrates reading in a table of numbers, packing them and adding them to a sum.
PRINT NOGEN
START 0
REGS
BEGIN BEGIN
OI INDCB+10,X'08' convert ASCII to EBCDIC
OPEN INDCB
LOOP GET INDCB,REC read a record
WTO REC1 write the record
PACK NBR,REC1
AP SUM,NBR
B LOOP loop
*
* EOJ processing
*
ATEND CLOSE INDCB
WTO MSG
ED RSLT,SUM
WTO RSLT
RETURN
*
* Literals
*
LTORG
*
* File DCB's
*
INDCB DCB LRECL=10,RECFM=F,MACRF=G,EODAD=ATEND,
DDNAME='INPUT1.DAT'
*
* input record
*
REC1 DS 0CL8 dummy overlapping short record
REC DS CL10 actual input record
NBR DS PL8
SUM DC PL4'0'
RSLT DC X'4020202020202120'
MSG DC C'DONE***************'
END BEGIN
|
Listing file for the above (.PRN):
ADDEX1 PAGE 1
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
000000 1 PRINT NOGEN
000000 2 START 0
000000 3 *+++++++ REGS
000000 00000000 4 R0 EQU 0
000000 00000001 5 R1 EQU 1
000000 00000002 6 R2 EQU 2
000000 00000003 7 R3 EQU 3
000000 00000004 8 R4 EQU 4
000000 00000005 9 R5 EQU 5
000000 00000006 10 R6 EQU 6
000000 00000007 11 R7 EQU 7
000000 00000008 12 R8 EQU 8
000000 00000009 13 R9 EQU 9
000000 0000000A 14 R10 EQU 10
000000 0000000B 15 R11 EQU 11
000000 0000000C 16 R12 EQU 12
000000 0000000D 17 R13 EQU 13
000000 0000000E 18 R14 EQU 14
000000 0000000F 19 R15 EQU 15
000000 20 *++++ BEGIN
000000 21 BEGIN CSECT
000000 22 USING *,15
000000 47F0F058 0058 23 B KZHQX002
000004 0B 24 DC AL1(11)
000005 C2C5C7C9D5404040 25 DC CL11'BEGIN '
000010 0000000000000000 26 HZQKX002 DC 18F'0'
000058 90ECD00C 000C 27 KZHQX002 STM 14,12,12(13)
00005C 50D0F014 0014 28 ST 13,HZQKX002+4
000060 18ED 29 LR 14,13
000062 41D0F010 0010 30 LA 13,HZQKX002
000066 50D0E008 0008 31 ST 13,8(0,14)
00006A 32 DROP 15
00006A 33 USING HZQKX002,13
00006A 9608D0DA 00EA 34 OI INDCB+10,X'08' convert ASCII to EBCDIC
00006E 35 *+++++++ OPEN INDCB
00006E 4120D0D0 00E0 36 LA 2,INDCB
000072 0A01 37 SVC 1
000074 38 *+++ GET INDCB,REC read a record
000074 00000074 39 LOOP EQU *
000074 4120D0D0 00E0 40 LA 2,INDCB
000078 4110D131 0141 41 LA 1,REC
00007C 0A05 42 SVC 5
00007E 43 *+++++++ WTO REC1 write the record
00007E 4300D139 0149 44 IC 0,REC1+L'REC1
000082 925BD139 0149 45 MVI REC1+L'REC1,C'$'
000086 4120D131 0141 46 LA 2,REC1
00008A 0AD1 47 SVC 209
00008C 4200D139 0149 48 STC 0,REC1+L'REC1
000090 F277D13BD131 014B 0141 49 PACK NBR,REC1
000096 FA37D143D13B 0153 014B 50 AP SUM,NBR
00009C 47F0D064 0074 51 B LOOP loop
. ADDEX1 PAGE 2
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
0000A0 52 *
0000A0 53 * EOJ processing
0000A0 54 *
0000A0 55
0000A0 56 *++++ CLOSE INDCB
0000A0 000000A0 57 ATEND EQU *
0000A0 4120D0D0 00E0 58 LA 2,INDCB
0000A4 0A02 59 SVC 2
0000A6 60 *+++ WTO MSG
0000A6 4300D162 0172 61 IC 0,MSG+L'MSG
0000AA 925BD162 0172 62 MVI MSG+L'MSG,C'$'
0000AE 4120D14F 015F 63 LA 2,MSG
0000B2 0AD1 64 SVC 209
0000B4 4200D162 0172 65 STC 0,MSG+L'MSG
0000B8 DE07D147D143 0157 0153 66 ED RSLT,SUM
0000BE 67 *+++++++ WTO RSLT
0000BE 4300D14F 015F 68 IC 0,RSLT+L'RSLT
0000C2 925BD14F 015F 69 MVI RSLT+L'RSLT,C'$'
0000C6 4120D147 0157 70 LA 2,RSLT
0000CA 0AD1 71 SVC 209
0000CC 4200D14F 015F 72 STC 0,RSLT+L'RSLT
0000D0 73 *+++++++ RETURN
0000D0 58DD0004 0004 74 L 13,4(13)
0000D4 98ECD00C 000C 75 LM 14,12,12(13)
0000D8 07FE 76 BR 14
0000DA 77 *
0000DA 78 * Literals
0000DA 79 *
0000E0 80 LTORG
0000E0 81 *
0000E0 82 * File DCB's
0000E0 83 *
0000E0 84
0000E0 85 *++++ DCB LRECL=10,RECFM=F,MACRF=G,EODAD=ATEND,
0000E0 86 *+++++++LABEL$ DDNAME='INPUT1.DAT'
0000E0 87 INDCB DS 0F,0CL86
0000E0 C1C4C3C2 88 DC C'ADCB'
0000E4 00000136 89 DC A(DCBDD010)
0000E8 FFFF00 90 DC X'FFFF',X'00'
0000EB E2C7C6 91 DC CL1'S',CL1'G',CL1'F'
0000EE 0A1A 92 DC X'0A1A'
0000F0 000A0000 93 DC H'10',H'0'
0000F4 000000A0000000A0 94 DC A(ATEND,ATEND,0)
000100 0000000000000000 95 DC 54X'00'
000136 C9D5D7E4E3F14BC4 96 DCBDD010 DC C'INPUT1.DAT',X'00'
000141 97
000141 98 *
000141 99 * input record
000141 100 *
000141 101
000141 102 REC1 DS 0CL8 dummy overlapping short record
. ADDEX1 PAGE 3
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
000141 103 REC DS CL10 actual input record
00014B 104 NBR DS PL8
000153 0000000C 105 SUM DC PL4'0'
000157 4020202020202120 106 RSLT DC X'4020202020202120'
00015F C4D6D5C55C5C5C5C 107 MSG DC C'DONE***************'
000000 108 END BEGIN
. ADDEX1 PAGE 4
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
SYMBOL VALUE LENGTH TYPE ID DEF# XREF#
$$CSECT 00000000 00000000 CST 01 00002
ATEND 000000A0 00000001 REL 02 00057 00094 00094 00094 00094
BEGIN 00000000 00000172 CST 02 00021 00108
DCBDD010 00000136 0000000A REL 02 00096 00089
HZQKX002 00000010 00000004 REL 02 00026 00033 00030 00028
INDCB 000000E0 00000004 REL 02 00087 00058 00040 00036 00034
KZHQX002 00000058 00000004 REL 02 00027 00023
LOOP 00000074 00000001 REL 02 00039 00051
MSG 0000015F 00000013 REL 02 00107 00065 00065 00063 00062 00062
00061 00061
NBR 0000014B 00000008 REL 02 00104 00050 00049
R0 00000000 00000001 ABS 00 00004
R1 00000001 00000001 ABS 00 00005
R10 0000000A 00000001 ABS 00 00014
R11 0000000B 00000001 ABS 00 00015
R12 0000000C 00000001 ABS 00 00016
R13 0000000D 00000001 ABS 00 00017
R14 0000000E 00000001 ABS 00 00018
R15 0000000F 00000001 ABS 00 00019
R2 00000002 00000001 ABS 00 00006
R3 00000003 00000001 ABS 00 00007
R4 00000004 00000001 ABS 00 00008
R5 00000005 00000001 ABS 00 00009
R6 00000006 00000001 ABS 00 00010
R7 00000007 00000001 ABS 00 00011
R8 00000008 00000001 ABS 00 00012
R9 00000009 00000001 ABS 00 00013
REC 00000141 0000000A REL 02 00103 00041
REC1 00000141 00000008 REL 02 00102 00049 00048 00048 00046 00045
00045 00044 00044
RSLT 00000157 00000008 REL 02 00106 00072 00072 00070 00069 00069
00068 00068 00066
SUM 00000153 00000004 REL 02 00105 00066 00050
. ADDEX1 PAGE 5
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
RELOCATION LISTING
SEG ADDRESS LENGTH SIGN RLD SEG
02 000000E4 4 + 02
02 000000F4 4 + 02
02 000000F8 4 + 02
LITERAL CROSS REFERENCE
|
Data file for the above (INPUT1.DAT):
00000010 00000020 00000030 00000040 |
Execution for the above:
C:\asmdisk\min>asm addex1
C:\asmdisk\min>del report.txt
Could Not Find C:\asmdisk\min\report.txt
C:\asmdisk\min>m370 addex1
C:\asmdisk\min>a370 addex1/lx
***********************************************
* PC/370 System Release 4.2 01/07/88 *
* Copyright (C) 1988 Donald S. Higgins *
* *
* You are encouraged to copy and share this *
* package with other users on the condition *
* the package is not distributed in modified *
* form, and that no fee is charged. If you *
* find PC/370 useful, send 45 dollars to the *
* address below to become registered user and *
* support continued shareware development. *
* Registered users will receive notices of *
* future PC/370 releases. *
* *
* Don Higgins *
* 6365 - 32 Avenue, North *
* St. Petersburg, Florida 33710 *
***********************************************
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
STATS SYM=00030 MAXSTD=00005 LIT=00000 MAXLTD=00000 BTMEM=51604
NO ERRORS FOUND
C:\asmdisk\min>l370 addex1/lx
***********************************************
* PC/370 System Release 4.2 01/07/88 *
* Copyright (C) 1988 Donald S. Higgins *
* *
* You are encouraged to copy and share this *
* package with other users on the condition *
* the package is not distributed in modified *
* form, and that no fee is charged. If you *
* find PC/370 useful, send 45 dollars to the *
* address below to become registered user and *
* support continued shareware development. *
* Registered users will receive notices of *
* future PC/370 releases. *
* *
* Don Higgins *
* 6365 - 32 Avenue, North *
* St. Petersburg, Florida 33710 *
***********************************************
PC/370 LINKAGE EDITOR OPTIONS ON = LXEFIP
STATS SYM=00002 MAXSTD=00001 BTMEM=57752
NO ERRORS FOUND
C:\asmdisk\min>addex1
00000010
00000020
00000030
00000040
DONE***************
100
C:\asmdisk\min>pause
Press any key to continue . . .
|
PRINT NOGEN
START 0
REGS
BEGIN BEGIN
OI INDCB+10,X'08' convert ASCII to EBCDIC
OPEN INDCB
LOOP GET INDCB,REC read a record
WTO REC1 write the record
LA R3,REC
MVI NEGFLG,C'0' make flag 0
L1 CLI 0(R3),C'-' minus sign found?
BE MINUS
CLI 0(R3),C'+' plus sign found
BE PLUS
CLI 0(R3),C' ' blank found
BE BLANK
CLI 0(R3),C'0' 0 or greater found?
BNL NUM
ERR WTO ERRMSG must be bad data
RETURN
MINUS MVI NEGFLG,C'1' set flag to 1
MVI 0(R3),C' ' make - a blank
B PCK
PLUS MVI 0(R3),C' ' make + a blank
B PCK
NUM CLI 0(R3),C'9' 9 or less?
BH ERR must be bad data
BLANK LA R3,1(R0,R3) increment pointer
LA R4,REC+8 get address of end
CR R3,R4 compare pointers
BL L1 loop if not done
PCK PACK NBR,REC1
CLI NEGFLG,C'1' is this number neg
BNE ADD no
NI NBR+7,X'FD' yes - make its sign D - CORRECTED
ADD AP SUM,NBR
B LOOP loop
*
* EOJ processing
*
ATEND CLOSE INDCB
WTO MSG
ED RSLT,SUM
WTO RSLT
RETURN
*
* Literals
*
LTORG
*
* File DCB's
*
INDCB DCB LRECL=10,RECFM=F,MACRF=G,EODAD=ATEND,
DDNAME='INPUT2.DAT'
*
* input record
*
REC1 DS 0CL8 dummy overlapping short record
REC DS CL10 actual input record
NBR DS PL8
NEGFLG DC C'0'
SUM DC PL4'0'
RSLT DC X'4020202020202120'
MSG DC C'DONE***************'
ERRMSG DC C'ERROR - BAD DATA'
END BEGIN
|
The PRN file is:
ADDEX2 PAGE 1
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
000000 1 PRINT NOGEN
000000 2 START 0
000000 3 *+++++++ REGS
000000 00000000 4 R0 EQU 0
000000 00000001 5 R1 EQU 1
000000 00000002 6 R2 EQU 2
000000 00000003 7 R3 EQU 3
000000 00000004 8 R4 EQU 4
000000 00000005 9 R5 EQU 5
000000 00000006 10 R6 EQU 6
000000 00000007 11 R7 EQU 7
000000 00000008 12 R8 EQU 8
000000 00000009 13 R9 EQU 9
000000 0000000A 14 R10 EQU 10
000000 0000000B 15 R11 EQU 11
000000 0000000C 16 R12 EQU 12
000000 0000000D 17 R13 EQU 13
000000 0000000E 18 R14 EQU 14
000000 0000000F 19 R15 EQU 15
000000 20 *++++ BEGIN
000000 21 BEGIN CSECT
000000 22 USING *,15
000000 47F0F058 0058 23 B KZHQX002
000004 0B 24 DC AL1(11)
000005 C2C5C7C9D5404040 25 DC CL11'BEGIN '
000010 0000000000000000 26 HZQKX002 DC 18F'0'
000058 90ECD00C 000C 27 KZHQX002 STM 14,12,12(13)
00005C 50D0F014 0014 28 ST 13,HZQKX002+4
000060 18ED 29 LR 14,13
000062 41D0F010 0010 30 LA 13,HZQKX002
000066 50D0E008 0008 31 ST 13,8(0,14)
00006A 32 DROP 15
00006A 33 USING HZQKX002,13
00006A 9608D152 0162 34 OI INDCB+10,X'08' convert ASCII to EBCDIC
00006E 35 *+++++++ OPEN INDCB
00006E 4120D148 0158 36 LA 2,INDCB
000072 0A01 37 SVC 1
000074 38
000074 39 *+++ GET INDCB,REC read a record
000074 00000074 40 LOOP EQU *
000074 4120D148 0158 41 LA 2,INDCB
000078 4110D1A9 01B9 42 LA 1,REC
00007C 0A05 43 SVC 5
00007E 44 *+++++++ WTO REC1 write the record
00007E 4300D1B1 01C1 45 IC 0,REC1+L'REC1
000082 925BD1B1 01C1 46 MVI REC1+L'REC1,C'$'
000086 4120D1A9 01B9 47 LA 2,REC1
00008A 0AD1 48 SVC 209
00008C 4200D1B1 01C1 49 STC 0,REC1+L'REC1
000090 50
000090 4130D1A9 01B9 51 LA R3,REC
. ADDEX2 PAGE 2
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
000094 92F0D1BB 01CB 52 MVI NEGFLG,C'0' make flag 0
000098 53
000098 95603000 0000 54 L1 CLI 0(R3),C'-' minus sign found?
00009C 4780D0C4 00D4 55 BE MINUS
0000A0 56
0000A0 954E3000 0000 57 CLI 0(R3),C'+' plus sign found
0000A4 4780D0D0 00E0 58 BE PLUS
0000A8 59
0000A8 95403000 0000 60 CLI 0(R3),C' ' blank found
0000AC 4780D0E0 00F0 61 BE BLANK
0000B0 62
0000B0 95F03000 0000 63 CLI 0(R3),C'0' 0 or greater found?
0000B4 47B0D0D8 00E8 64 BNL NUM
0000B8 65
0000B8 66 *++ WTO ERRMSG must be bad data
0000B8 4300D1EB 01FB 67 ERR IC 0,ERRMSG+L'ERRMSG
0000BC 925BD1EB 01FB 68 MVI ERRMSG+L'ERRMSG,C'$'
0000C0 4120D1DB 01EB 69 LA 2,ERRMSG
0000C4 0AD1 70 SVC 209
0000C6 4200D1EB 01FB 71 STC 0,ERRMSG+L'ERRMSG
0000CA 72 *+++++++ RETURN
0000CA 58DD0004 0004 73 L 13,4(13)
0000CE 98ECD00C 000C 74 LM 14,12,12(13)
0000D2 07FE 75 BR 14
0000D4 76
0000D4 92F1D1BB 01CB 77 MINUS MVI NEGFLG,C'1' set flag to 1
0000D8 92403000 0000 78 MVI 0(R3),C' ' make - a blank
0000DC 47F0D0EE 00FE 79 B PCK
0000E0 80
0000E0 92403000 0000 81 PLUS MVI 0(R3),C' ' make + a blank
0000E4 47F0D0EE 00FE 82 B PCK
0000E8 83
0000E8 95F93000 0000 84 NUM CLI 0(R3),C'9' 9 or less?
0000EC 4720D0A8 00B8 85 BH ERR must be bad data
0000F0 86
0000F0 41303001 0001 87 BLANK LA R3,1(R0,R3) increment pointer
0000F4 4140D1B1 01C1 88 LA R4,REC+8 get address of end
0000F8 1934 89 CR R3,R4 compare pointers
0000FA 4740D088 0098 90 BL L1 loop if not done
0000FE 91
0000FE F277D1B3D1A9 01C3 01B9 92 PCK PACK NBR,REC1
000104 95F1D1BB 01CB 93 CLI NEGFLG,C'1' is this number neg
000108 4770D100 0110 94 BNE ADD no
00010C 94FDD1BA 01CA 95 NI NBR+7,X'FD' yes - make its sign D
000110 FA37D1BCD1B3 01CC 01C3 96 ADD AP SUM,NBR
000116 47F0D064 0074 97 B LOOP loop
00011A 98 *
00011A 99 * EOJ processing
00011A 100 *
00011A 101
00011A 102 *++++ CLOSE INDCB
. ADDEX2 PAGE 3
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
00011A 0000011A 103 ATEND EQU *
00011A 4120D148 0158 104 LA 2,INDCB
00011E 0A02 105 SVC 2
000120 106 *+++ WTO MSG
000120 4300D1DB 01EB 107 IC 0,MSG+L'MSG
000124 925BD1DB 01EB 108 MVI MSG+L'MSG,C'$'
000128 4120D1C8 01D8 109 LA 2,MSG
00012C 0AD1 110 SVC 209
00012E 4200D1DB 01EB 111 STC 0,MSG+L'MSG
000132 DE07D1C0D1BC 01D0 01CC 112 ED RSLT,SUM
000138 113 *+++++++ WTO RSLT
000138 4300D1C8 01D8 114 IC 0,RSLT+L'RSLT
00013C 925BD1C8 01D8 115 MVI RSLT+L'RSLT,C'$'
000140 4120D1C0 01D0 116 LA 2,RSLT
000144 0AD1 117 SVC 209
000146 4200D1C8 01D8 118 STC 0,RSLT+L'RSLT
00014A 119 *+++++++ RETURN
00014A 58DD0004 0004 120 L 13,4(13)
00014E 98ECD00C 000C 121 LM 14,12,12(13)
000152 07FE 122 BR 14
000154 123 *
000154 124 * Literals
000154 125 *
000158 126 LTORG
000158 127 *
000158 128 * File DCB's
000158 129 *
000158 130
000158 131 *++++ DCB LRECL=10,RECFM=F,MACRF=G,EODAD=ATEND,
000158 132 *+++++++LABEL$ DDNAME='INPUT2.DAT'
000158 133 INDCB DS 0F,0CL86
000158 C1C4C3C2 134 DC C'ADCB'
00015C 000001AE 135 DC A(DCBDD012)
000160 FFFF00 136 DC X'FFFF',X'00'
000163 E2C7C6 137 DC CL1'S',CL1'G',CL1'F'
000166 0A1A 138 DC X'0A1A'
000168 000A0000 139 DC H'10',H'0'
00016C 0000011A0000011A 140 DC A(ATEND,ATEND,0)
000178 0000000000000000 141 DC 54X'00'
0001AE C9D5D7E4E3F24BC4 142 DCBDD012 DC C'INPUT2.DAT',X'00'
0001B9 143
0001B9 144 *
0001B9 145 * input record
0001B9 146 *
0001B9 147
0001B9 148 REC1 DS 0CL8 dummy overlapping short record
0001B9 149 REC DS CL10 actual input record
0001C3 150 NBR DS PL8
0001CB F0 151 NEGFLG DC C'0'
0001CC 0000000C 152 SUM DC PL4'0'
0001D0 4020202020202120 153 RSLT DC X'4020202020202120'
. ADDEX2 PAGE 4
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
0001D8 C4D6D5C55C5C5C5C 154 MSG DC C'DONE***************'
0001EB C5D9D9D6D9406040 155 ERRMSG DC C'ERROR - BAD DATA'
000000 156 END BEGIN
. ADDEX2 PAGE 5
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
SYMBOL VALUE LENGTH TYPE ID DEF# XREF#
$$CSECT 00000000 00000000 CST 01 00002
ADD 00000110 00000006 REL 02 00096 00094
ATEND 0000011A 00000001 REL 02 00103 00140 00140 00140 00140
BEGIN 00000000 000001FB CST 02 00021 00156
BLANK 000000F0 00000004 REL 02 00087 00061
DCBDD012 000001AE 0000000A REL 02 00142 00135
ERR 000000B8 00000004 REL 02 00067 00085
ERRMSG 000001EB 00000010 REL 02 00155 00071 00071 00069 00068 00068
00067 00067
HZQKX002 00000010 00000004 REL 02 00026 00033 00030 00028
INDCB 00000158 00000004 REL 02 00133 00104 00041 00036 00034
KZHQX002 00000058 00000004 REL 02 00027 00023
L1 00000098 00000004 REL 02 00054 00090
LOOP 00000074 00000001 REL 02 00040 00097
MINUS 000000D4 00000004 REL 02 00077 00055
MSG 000001D8 00000013 REL 02 00154 00111 00111 00109 00108 00108
00107 00107
NBR 000001C3 00000008 REL 02 00150 00096 00095 00092
NEGFLG 000001CB 00000001 REL 02 00151 00093 00077 00052
NUM 000000E8 00000004 REL 02 00084 00064
PCK 000000FE 00000006 REL 02 00092 00082 00079
PLUS 000000E0 00000004 REL 02 00081 00058
R0 00000000 00000001 ABS 00 00004 00087
R1 00000001 00000001 ABS 00 00005
R10 0000000A 00000001 ABS 00 00014
R11 0000000B 00000001 ABS 00 00015
R12 0000000C 00000001 ABS 00 00016
R13 0000000D 00000001 ABS 00 00017
R14 0000000E 00000001 ABS 00 00018
R15 0000000F 00000001 ABS 00 00019
R2 00000002 00000001 ABS 00 00006
R3 00000003 00000001 ABS 00 00007 00089 00087 00087 00084 00081
00078 00063 00060 00057 00054
00051 00087 00051
R4 00000004 00000001 ABS 00 00008 00089 00088 00088
R5 00000005 00000001 ABS 00 00009
R6 00000006 00000001 ABS 00 00010
R7 00000007 00000001 ABS 00 00011
R8 00000008 00000001 ABS 00 00012
R9 00000009 00000001 ABS 00 00013
REC 000001B9 0000000A REL 02 00149 00088 00051 00042
REC1 000001B9 00000008 REL 02 00148 00092 00049 00049 00047 00046
00046 00045 00045
RSLT 000001D0 00000008 REL 02 00153 00118 00118 00116 00115 00115
00114 00114 00112
SUM 000001CC 00000004 REL 02 00152 00112 00096
. ADDEX2 PAGE 6
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
LOC ADR1 ADR2 LINE LABEL OP OPERANDS
RELOCATION LISTING
SEG ADDRESS LENGTH SIGN RLD SEG
02 0000015C 4 + 02
02 0000016C 4 + 02
02 00000170 4 + 02
LITERAL CROSS REFERENCE
|
The input data is:
C:\asmdisk\min>type input2.dat
10
-20
+30
40
|
The execution is:
C:\asmdisk\min>asm addex2
C:\asmdisk\min>del report.txt
Could Not Find C:\asmdisk\min\report.txt
C:\asmdisk\min>m370 addex2
C:\asmdisk\min>a370 addex2/lx
***********************************************
* PC/370 System Release 4.2 01/07/88 *
* Copyright (C) 1988 Donald S. Higgins *
* *
* You are encouraged to copy and share this *
* package with other users on the condition *
* the package is not distributed in modified *
* form, and that no fee is charged. If you *
* find PC/370 useful, send 45 dollars to the *
* address below to become registered user and *
* support continued shareware development. *
* Registered users will receive notices of *
* future PC/370 releases. *
* *
* Don Higgins *
* 6365 - 32 Avenue, North *
* St. Petersburg, Florida 33710 *
***********************************************
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
STATS SYM=00040 MAXSTD=00005 LIT=00000 MAXLTD=00000 BTMEM=51272
NO ERRORS FOUND
C:\asmdisk\min>l370 addex2/lx
***********************************************
* PC/370 System Release 4.2 01/07/88 *
* Copyright (C) 1988 Donald S. Higgins *
* *
* You are encouraged to copy and share this *
* package with other users on the condition *
* the package is not distributed in modified *
* form, and that no fee is charged. If you *
* find PC/370 useful, send 45 dollars to the *
* address below to become registered user and *
* support continued shareware development. *
* Registered users will receive notices of *
* future PC/370 releases. *
* *
* Don Higgins *
* 6365 - 32 Avenue, North *
* St. Petersburg, Florida 33710 *
***********************************************
PC/370 LINKAGE EDITOR OPTIONS ON = LXEFIP
STATS SYM=00002 MAXSTD=00001 BTMEM=57752
NO ERRORS FOUND
C:\asmdisk\min>addex2
10
-20
+30
40
DONE***************
60
C:\asmdisk\min>pause
Press any key to continue . . .
|
Notes: The above scans the input looking for blanks, numbers and either a plus or minus sign. If it detects a minus sign, it sets a flag. Plus and minus signs are replaced by blanks (Hex 40). After the number has been packed, it checks the flag. If the flag is true - a minus sign was found - it performs and AND-IMMEDIATE (NI) on the last byte of the packed number. The packed number, after the PACK instruction is positive due to the zone on the final numeric character (Hex F) becomming the digit portion of the final byte (PACK reverses the zone and digit in the last byte of the packed field). By AND'ing Hex FD with this byte, the zone portion is retained and the digit portion becomes Hex D.
Scanning input fields is important so the architecture provided for a single instruction to do this, the TRT (Translate and Test) instruction. The TRT uses a table (second operand) and a string (first operand). Bytes in the string are successively (left to right) used to index into the table. The table is 256 bytes long. The byte found in the table determines what should happen:
Building a TRT table to halt on non-numeric and non-blanks:
TAB DC 256X'01'
ORG TAB+C' '
DC X'00'
ORG TAB+C'0'
DC 10X'00'
ORG
|
In the above, first you build a table of 256 bytes all initialized to X01 (these bytes, since they are not zero, will halt the TRT), Then, you back into the table and replace the byte correcponding to the offset of blank (X40) with X00 and move again to the offset associated with a character zero (XF0) and replace it and the next nine bytes with X00. The ORG directive resets the location counted to the value specified. An ORG with no argument resets the location counter to the highes value it has ever held.
The effect of the above is to create a table mainly of X01 codes except in the offset positions for blank and the character versions of the numbers from zero to nine, inclusive.
Doing th above add example with a TRT:
PRINT NOGEN
START 0
REGS
BEGIN BEGIN
OI INDCB+10,X'08' convert ASCII to EBCDIC
OPEN INDCB
LOOP GET INDCB,REC read a record
WTO REC1 write the record
MVI NEGFLG,C'0' set flag to 0
TRT REC1,TAB
BE PCK only blanks and numbers
CLI 0(R1),C'-' minus sign found?
BNE PLUS
MVI NEGFLG,C'1' set flag to 1
MVI 0(R1),C' ' make - a blank
B PCK
PLUS CLI 0(R1),C'+' plus sign found
BNE PCK
MVI 0(R1),C' ' make + a blank
B PCK
ERR WTO ERRMSG must be bad data
RETURN
PCK PACK NBR,REC1
CLI NEGFLG,C'1' is this number neg
BNE ADD no
NI NBR+7,X'FB' yes - make its sign D
ADD AP SUM,NBR
B LOOP loop
*
* EOJ processing
*
ATEND CLOSE INDCB
WTO MSG
MVC RSLT,=X'4020202020202120'
ED RSLT,SUM
WTO RSLT
RETURN
*
* Literals
*
LTORG
*
* File DCB's
*
INDCB DCB LRECL=10,RECFM=F,MACRF=G,EODAD=ATEND,
DDNAME='INPUT2.DAT'
*
* input record
*
REC1 DS 0CL8 dummy overlapping short record
REC DS CL10 actual input record
NBR DS PL8'0'
NEGFLG DC C'0'
SUM DC PL4'0'
RSLT DC X'4020202020202120'
MSG DC C'DONE***************'
ERRMSG DC C'ERROR - BAD DATA'
TAB DC 256X'01'
ORG TAB+C'0'
DC 10X'00'
ORG TAB+C' '
DC X'00'
ORG
END BEGIN
|
The results are the same as for the above.
PRINT NOGEN
START 0
REGS
BEGIN BEGIN
OI INDCB+10,X'08' convert ASCII to EBCDIC
OPEN INDCB
LOOP GET INDCB,REC read a record
WTO REC1 write the record
LA R3,REC1
TRT 0(L'REC1,R3),TAB
BE EXIT only blanks found
LR R3,R1
LA R5,WORD
MVC 0(1,R5),0(R3)
L1 LA R3,1(R0,R3)
LA R5,1(R0,R5)
LA R4,REC1+30
CR R3,R4
BNL PRNT
CLI 0(R3),C' '
BE PRNT
MVC 0(1,R5),0(R3)
B L1
PRNT WTO WORD
MVI WORD,C' '
MVC WORD+1(L'WORD-1),WORD
B LOOP
*
* EOJ processing
*
ATEND CLOSE INDCB
WTO MSG
EXIT RETURN
*
* Literals
*
LTORG
*
* File DCB's
*
INDCB DCB LRECL=32,RECFM=F,MACRF=G,EODAD=ATEND,
DDNAME='INPUT3.DAT'
*
* input record
*
REC1 DS 0CL30 dummy overlapping short record
REC DS CL32 actual input record
WORD DC CL30' '
MSG DC C'***** DONE *****'
ERRMSG DC C'ERROR - BAD DATA'
TAB DC 256X'01'
ORG TAB+C' '
DC X'00'
ORG
END BEGIN
|
The input images:
TEST1 *
TEST2 *
TEST3 *
|
Execution:
C:\asmdisk\min>asm scan
C:\asmdisk\min>del report.txt
Could Not Find C:\asmdisk\min\report.txt
C:\asmdisk\min>m370 scan
C:\asmdisk\min>a370 scan/lx
***********************************************
* PC/370 System Release 4.2 01/07/88 *
* Copyright (C) 1988 Donald S. Higgins *
* *
* You are encouraged to copy and share this *
* package with other users on the condition *
* the package is not distributed in modified *
* form, and that no fee is charged. If you *
* find PC/370 useful, send 45 dollars to the *
* address below to become registered user and *
* support continued shareware development. *
* Registered users will receive notices of *
* future PC/370 releases. *
* *
* Don Higgins *
* 6365 - 32 Avenue, North *
* St. Petersburg, Florida 33710 *
***********************************************
PC/370 CROSS ASSEMBLER OPTIONS=LXACE
STATS SYM=00033 MAXSTD=00005 LIT=00000 MAXLTD=00000 BTMEM=51472
NO ERRORS FOUND
C:\asmdisk\min>l370 scan/lx
***********************************************
* PC/370 System Release 4.2 01/07/88 *
* Copyright (C) 1988 Donald S. Higgins *
* *
* You are encouraged to copy and share this *
* package with other users on the condition *
* the package is not distributed in modified *
* form, and that no fee is charged. If you *
* find PC/370 useful, send 45 dollars to the *
* address below to become registered user and *
* support continued shareware development. *
* Registered users will receive notices of *
* future PC/370 releases. *
* *
* Don Higgins *
* 6365 - 32 Avenue, North *
* St. Petersburg, Florida 33710 *
***********************************************
PC/370 LINKAGE EDITOR OPTIONS ON = LXEFIP
STATS SYM=00002 MAXSTD=00001 BTMEM=57752
NO ERRORS FOUND
C:\asmdisk\min>scan
TEST1 *
TEST1
TEST2 *
TEST2
TEST3 *
TEST3
***** DONE *****
C:\asmdisk\min>pause
|
.
.
.
SR R5,R5
LA R6,TAB
LOOP STC R5,0(0,R6) * init whole TAB
LA R6,1(0,R6)
LA R5,1(0,R5)
CL R5,CODE
BNH LOOP
LA R6,TAB+C'a' * re-set beginning at a
L R5,AAA
LOOP1 STC R5,0(0,R6)
LA R5,1(0,R5)
LA R6,1(0,R6)
CL R5,AAA1
BNH LOOP1
.
.
.
DS 0F * align to full word
AAA DC X'000000' * 3 bytes of zeros
DC C'A' * 1 byte contianing A
AAA1 DC X'000000'
DC C'Z'
CODE DC X'000000FF'
TAB DS 256C
|
A byte is 8 bits. You can isolate the high order bits of a byte by shifting the byte right by 4 thus causing loss of the low order 4 bits. You can isolate the lower 4 bits by ANDing the byte with a mask 0f B'00001111' (X'0F').
If the byte is in memory, load it into a register using the Insert Character instruction (IC). The IC loads the byte from the address designated by the second operand into the low order 8 bits of the register designated as the first operand. The high order 24 bits of the register are unchenged. Thus, you should probably zero out the register before loading the character.
Once the character is loaded, you may proceed to extract the 4 bit fields. These can then, as done in class, be used to index into a table to get the Hex character code equivalent. The following fragment extracts the low and high order bits, looks them up in the table and puts the character code found into an output string.
.
.
.
* Assume: R6 points to the byte in memory to be worked on.
* R5 points to the next available byte in the output string
SR R4,R4
IC R4,0(R0,R6)
SRL R4,4
LA R4,TAB(R4) * R4 becomes the index register
MVC 0(1,R5),0(R4) * move to output
LA R5,1(R0,R5)
IC R4,0(R0,R6)
N R4,MASK * zero all but lower 4 bits
LA R4,TAB(R4)
MVC 0(1,R5),0(R4) * move to output
LA R5,1(R0,R5)
.
.
.
HEX DC C'0123456789ABCDEF'
DS 0F * alignment
MASK DC X'0000000F'
|
The SRL is the Shift Right Logical instrunction. The other shifts are:
SRA Shift Right Arithmetic SLL Shift Left Logical SLA Shift Left Arithmetic SLDL Shift Left Double Logical SRDL Shift Right Double Logical SLDA Shift Left Double Arithmetic SRDA Shift Right Double Arithmetic
The Arithmetic shifts take into account the sign of the value. On right shifts, bits like the sign are shifted in at the hight end. On left shifts, if a bit unlike the sign bit is shifted into the sign bit position, an overflow takes place. On a lft shift, zeros are shifted into the low order positions.
The Logical shifts treat the values as unsigned bit strings. Zeros are shifted in at the high and low ends as needed.
The Double shifts operate of a 64 bit value formed from an even-odd pair of registers such as R2 and R3, R0 and R1, etc.