This chapter covers decimal
data, which refers to numeric data that are handled one digit at a time as
opposed to binary integer arithmetic or floating point arithmetic.As will be soon noticed, the decimal format is
particularly well adapted to the accounting and other business computation that
predominates in the companies which represent IBM’s primary markets.

In the IBM S/370 architecture,
there are two primary types of decimal data: zoned decimal data and packed
decimal data.As far as your author can
determine, the zoned format serves mostly as an intermediate form between
digital character data in EBCDIC form and the packed decimal format that is
used for many computations.

Zoned Decimal Data

The zoned decimal format is a modification
of the EBCDIC format.It seems not to be
used in any numeric processing and might best be viewed as an intermediate form
in the process of translating digits in EBCDIC form into the internal
representation of a number.The format
seems to be a modification to facilitate processing decimal strings of variable
length.

The
length of zoned data may be from 1 to 16 digits, stored in 1 to 16 bytes.Note that, as in the character
representation, this format calls for one byte per digit.

We have
the address of the first byte for the decimal data, but need some “tag” to denote
the last (rightmost) byte, as the format is not fixed length.The assembler places a “sign zone” for the
rightmost byte of the zoned data.The common standard isX‘C’ for non–negative
numbers, andX‘D’
for negative numbers.

Other
than the placing of a hexadecimal digit X‘C’ or X‘D’ for the zone
part of the last digit, the zoned decimal format is rather similar to the
EBCDIC format.

Consider
the negative number –12345, and its various
representations in which the spaces are inserted for readability only.Note that X‘60’ is the EBCDIC
representation of the “–”.

As a
string of EBCDIC characters it is hexadecimal60 F1 F2 F3 F4 F5.

In the
zoned decimal representation it is hexadecimalF1
F2 F3 F4 D5.

As packed
decimal format (to be discussed soon) it is stored as 12 34 5D.

There are a few more things that
might be said about the zoned format, such as how to declare a zoned decimal
constant (the format type is Z).As your
author views the zoned format as an intermediate format, we shall discuss it
further only in the context of conversion between EBCDIC characters and packed
decimal digits.

Packed Decimal Data

The preferred use of packed
decimal data format was introduced in Chapter 4, where it was shown not to have
the round–off problem that is commonly found in all floating–point
formats.The standard floating–point
formats can guarantee either seven digits of accuracy or fifteen digits of accuracy.People in business want all digits to be
accurate.If a sales total takes 17
digits to represent, all 17 digits in the number must be correct.

A packed decimal constant is a
signed integer, with between 1 and 31 digits (inclusive).
The number of digits is always odd, with a 0 being prefixed to a constant of
even length.

A sign “half byte” or hexadecimal digit is appended to the
representation.The common
sign–representing hexadecimal digits are as follows:

Cnon–negative

Dnegative

Fnon–negative, seen in the results of a
PACK instruction.

If a DC (Define Constant)
declarative is used to initialize storage with a packed decimal
value, one may use the length attribute.Possibly the only good use for this would be to
produce a right–adjusted value with a number of leading zeroes.

For exampleDC PL6’1234’ becomes

00

00

00

01

23

4C

Remember that each of these bytes holds two hexadecimal
digits, not the value
indicated in decimal, so 23 is stored as 0010 0011 and 4C as 0100
1100.

Some Examples and Cautions

Here are some examples of
numbers being represented in packed decimal format.

DC P‘+370’ becomes 370C

DC P‘–500’ becomes500D

DC P‘+92’ becomes 092C

Here are some uses that, while
completely logical, might best be avoided.The problem with the first example is that the length in bytes is not
sufficient to store the packed decimal number, so that the five leftmost digits
are truncated.The second example shows
the use of a DC declarative to define three constants in a manner that is
difficult to read.

P1DC PL2‘12345678’is truncated to become 678C.Why give a value only to remove most
of it?

PCONDC PL2‘123’,‘–456’,‘789’

This
creates three constants, stored as 123C, 456D, and 789C.Only the first constant can be
addressed directly.

I would prefer the following
sequence, with the labels P2 and P3 being optional.

P1DC PL2‘123’

P2DC PL2‘–456’

P3DC PL2‘789’

More Examples

The
packed decimal format is normally considered as a fixed point format, with
a specified number of digits to the right of the decimal point.It is important to note that decimal points
are ignored when declaring a packed value.When such are found in a constant, they are treated by the assembler as
comments.

Consider
the following examples and the assembly of each.Note that spaces have been
inserted between the bytes for readability only.They do not occur in the object code.

We now
discuss a number of ways in which the operand addresses for character instructions
may be presented in the source code.One
should note that each of these source code representations will give rise to
object code that appears almost identical.These examples are taken from Peter Abel [R_02, pages 273 &
274].Consider the following source
code, taken from Abel.This is based on
a conversion of a weight expressed in kilograms to its equivalent in pounds;
assuming 1kg. = 2.2 lb.Physics students
will please ignore the fact that the kilogram measures mass and not weight.

ZAPPOUNDS,KGSMOVE KGS TO POUNDS

MPPOUNDS,FACTORMULTIPLY BY THE
FACTORSRPPOUNDS,63,5ROUND TO ONE DECIMAL PLACE

KGSDCPL3‘12.53’LENGTH 3 BYTES

FACTORDCPL2‘2.2’LENGTH 2 BYTES, AT
ADDRESSS KGS+3

POUNDSDSPL5LENGTH 5 BYTES, AT
ADDRESS KGS+5

The value produced is 12.53·2.2 =
27.566, which is rounded to 27.57.

The
instructions we want to examine in some detail are the MP and ZAP,
each of which
is a type SS instruction with source code format OP D1(L1,B1),D2(L2,B2).Each of the two operands in these
instructions has a length specifier.In
the first example of the use of explicit base registers, we assign a base
register to represent the address of each of the arguments.The above code becomes the following:

LA R6,KGSADDRESS OF LABEL KGS

LA R7,FACTORADDRESS

LA R8,POUNDS

ZAP 0(5,8),0(3,6)

MP0(5,8),0(2,7)

SRP 0(5,8),63,5

Each of the
arguments in the MP and ZAP have the following form:

Recall the
definitions of the three labels, seen just above.We analyze the instructions.

ZAP 0(5,8),0(3,6)Destination is at offset 0 from the address stored in R8. The
destination has length 5 bytes.

Source is at offset 0 from the
address storedin R6.The source has length 3 bytes.

MP0(5,8),0(2,7)Destination is at offset 0 from the address stored in R8. The
destination has length 5 bytes.

Source is at offset 0 from the
address storedin R7.The source has length 2 bytes.

But recall
the order in which the labels are declared.The implicit assumption that the labels are in consecutive memory
locations will here be made explicit.

KGSDCPL3‘12.53’LENGTH 3 BYTES

FACTORDCPL2‘2.2’LENGTH 2 BYTES, AT
ADDRESSS KGS+3

POUNDSDSPL5LENGTH 5 BYTES, AT
ADDRESS KGS+5

In this version of the code, we use the
label KGS as the base address and reference all other addresses by displacement
from that one.Here is the code.

LA R6,KGSADDRESS OF LABEL KGS

ZAP 5(5,6),0(3,6)

MP5(5,6),3(2,6)

SRP 5(5,6),63,5

Each of the
arguments in the MP and ZAP have the following form:

Recall the
definitions of the three labels, seen just above.We analyze the instructions.

ZAP 5(5,6),0(3,6)Destination is at offset 5 from the address stored in R6. The
destination has length 5 bytes.

Source
is at offset 0 from the address storedin R6.The source has length 3 bytes.

MP5(5,6),3(2,6)Destination is at offset 5 from the address stored in R6. The
destination has length 5 bytes.

Source
is at offset 3 from the address storedin R6.The source has length 2 bytes.

In other
words, the base/displacement 6000 refers to a displacement of 0
from the address stored in register 6, which is being used as an explicit base
register for this operation.As
the address in R6 is that of KGS, this value represents the address KGS.This is the object code address generated in
response to the source code fragment 0(3,6).

The
base/displacement 6003 refers to a displacement of 3
from the address stored in register 6, which is being used as an explicit base
register for this operation.As the
address in R6 is that of KGS, this value represents the address KGS+3,
which is the address FACTOR.This is the object code address generated in
response to the source code fragment 3(2,6).

The
base/displacement 6005 refers to a displacement of 5
from the address stored in register 6, which is being used as an explicit base
register for this operation.As the
address in R6 is that of KGS, this value represents the address KGS+5,
which is the address POUNDS.This is the object code address generated in
response to the source code fragment 5(5,6).

It is worth
notice, even at this point, that the use of a single register as the base from
which to reference a block of data declarations is quite suggestive of what is
done with a DSECT, also called a “Dummy Section”.

Packed Decimal: Moving Data

There are
two instructions that might be used to move packed decimal data from one memory
location to another.The preferred
instruction is ZAP (Zero and Add Packed).

MVCS1,S2Copy
characters from location S2 to location S1

ZAPS1,S2Copy the
numeric value from location S2 to location S1.

Each of
the two instructions can lead to truncation if the length of the receiving
area, S1, is less than the source memory area, S2.If the lengths of the receiving field and the
sending field are equal, either instruction can be used and produce correct
results.

The real
reason for preferring the ZAP instruction for moving packed decimal data comes
when the length of the receiving field is larger than that of the sending
field.The ZAP instruction copies the
contents of the sending field right to left and then pads the receiving field
with zeroes, producing a correct result.

The MVC
instruction will copy extra bytes if the receiving field is longer than the sending
field.The MVC instruction makes a
left–to–right copy and will copy the required number of bytes, probably copying
garbage.Consider the following example.

F1DC P‘0000000’stored as 0000 000C, this takes 4 bytes,

F2DC P‘123’stored as 12 3C, this takes 2 bytes.

F3DC P‘4567’stored as 04 56 7C, this takes 3 bytes.

Executing
ZAP
F1, F2 will cause F1 to be set to 0000 123C, which is
correct.

Executing
MVC
F1, F2 will set F1 to 123C 0456, which not only is the
wrong answer, but also fails to be in any recognizable packed decimal format.

Bottom
line:Use the ZAP instruction to move
packed decimal data.

Packed Decimal Data:
ZAP, AP, CP, and SP

We have four
instructions with similar format.

ZAPS1,S2Zero S1 and add packed S2(This
is the move discussed above)

APS1,S2Add packed S2 to S1

CPS1,S2Compare S1 to S2, assuming the packed
decimal format.

SPS1,S2Subtract packed S2 from S1.

These
are of the form OP D1(L1,B1),D2(L2,B2), which provide a 4–bit number
representing the length for each of the two operands.The object code format is as follows.

Type

Bytes

Form

1

2

3

4

5

6

SS(2)

6

D1(L1,B1),D2(L2,B2)

OP

L1
L2

B1
D1

D1D1

B2
D2

D2D2

The first byte contains the
operation code, which is X‘F8’ for ZAP, X‘F9’
for CP,
X‘FA’
for AP,
X‘FB’
for SP.

The
second byte contains two hexadecimal digits, each representing an operand
length.

Each
of L1 and L2 encodes one less than the length of the
associated operand.This
allows 4 bits to encode the numbers 1 through 16, but disallows arguments of
length 0.

The
next four bytes contain two addresses in base register/displacement format.

Packed Decimal Data: Additional Considerations

For all four
instructions, the second operand must be a valid packed field terminated with a
valid sign.The usual values are ‘C’,
‘D’,
and occasionally ‘F’, though the hexadecimal digits ‘A’,
‘B’,
and ‘E’
are legal.As noted above, the sign
digit ‘D’
is standard for negative numbers, while the sign digit ‘C’ is standard for
non–negative numbers.The sign digit ‘F’
will be seen in data converted from Zoned Decimal by the PACK instruction.

For AP,
CP, and SP, the first operand must be a valid packed field terminated with a
valid
sign.For ZAP, the only consideration is
that the destination field be large enough.

If either
the sending field or the destination field (AP and SP) have just been created by
a PACK instruction, the sign half–byte may be represented by the sign digit ‘F’.
This is changed by the processing to ‘C’ or ‘D’ as necessary.

Some
textbook hint that using ZAP to transfer a packed decimal number with ‘F’
as the sign half–byte will convert that to ‘C’.This seems reasonable.

Any
packed decimal value with a sign half–byte of D (for negative) is considered to
sort less than any packed decimal value with a sign half–byte of C or F
(positive).This follows the standard
arithmetic in which any negative number is less than any positive number.

The
number 0 is always represented as 0C (possibly with more leading
zeroes), but
is never validly represented as 0D.There is no negative zero.

Example of Packed
Decimal Instructions

The
form is OP
D1(L1,B1),D2(L2,B2).The
object code format is as follows:

The first value is X‘3’,
or 3 decimal.The first operand is 4
bytes long.

The second value is X‘2’,
or 2 decimal.The second operand is 3
bytes long.

The
two–byte field 35 0A indicates that register 3 is used as the base
register
for the first operand, which is at displacement X‘50A’.

The
two–byte field 35 2C indicates that register 3 is used as the base
register
for the second operand, which is at displacement X‘52C’.

It is quite common for both
operands to use the same base register.

Condition Codes

Each of
the ZAP, AP, and SP instructions will set the condition codes.As a result,
one may execute conditional branches based on these operations.The branches are:

BZBranch
ZeroBNZBranch Not Zero

BMBranch
if negativeBNMBranch if not negative

BPBrach
if positiveBNPBranch if not positive

BOBranch
on overflowBNOBranch if overflow has not occurred.

An overflow will occur if the receiving
field is not large enough to accept the result.

My guess
is that leading zeroes are not considered in this; so that the seven–digit
packed
decimal number 0000123 can be moved to a field accepting four digit packed
numbers.

Additional Rules for ZAP, AP, and SP

These rules
are as follows:

1.The
maximum length for each field is 16 bytes, allowing for a maximum of 31 digits.Either field, or both, may have an explicit
length operand with a maximum value of 16.Remember that this operand is a byte length.

2.If
the operand 1 (destination) field is shorter than the operand 2 (source) field,
a program interrupt may
occur.The length of the first field
should be sized for the expected result of the
operation and not just based on the length associated with the first value.For addition, the operand 1 field should be
one digit larger than the lengths of either of
the values to be added.

3.The
CPU extends the shorter field (presumably that associated with the secondoperand) to that of the longer
field by left padding with zeroes.This
is necessary for the results to be in
accordance with standard arithmetic.

Examples of ZAP, AP, and SP

Here are
a few examples of the use of the three instructions AP, SP, and ZAP.The examples are to be viewed as independent
executions of code, so that the values associated with the data labels are
always the same at the beginning of each.

Suppose
that we start with definitions as follows.

P0DC P‘666’Stored as 66 6C

P1DC
P‘222’ Stored as 22 2C

P2DC
P‘1234’Stored as 01 23 4C

P3DC P‘1234567’Stored as 12 34 56 7C

For these
examples, we assume that the data stored represent integer values, and that
none has an implied decimal or “digits to the right of the decimal”.

In other
words, the arithmetic is not blindly done left to right, but with the digits
“lined up” as one would expect in standard arithmetic.

CASE6
AP P1,P1RESULTS IN P1 = 44 4C.

CASE7AP P0,P0This causes an overflow.

Here we
see the importance of design so that the first argument can store not just its
initial value, but also the result of any reasonably contemplated arithmetic
operation.

CASE8SP P0,P0RESULT IS 0, PRESUMABLY STORED AS 0C.

Comparing Packed
Decimal Values

The rules
for the CP instruction are the same as those for the AP and SP instructions.

1.Both
operands must contain valid packed data, with maximum length of 16 bytes.Either operand or both may
contain an explicit length indicator.

2.If
the fields are not of the same length, the CPU extends the shorter field by
paddingwith left zeroes to the length
of the longer field.The comparison
remains valid.

3.All
comparisons are as in standard algebra.+0
is considered equal to –0, butotherwise any positive value
is larger than any negative value.

The CP (Compare Packed) instruction is used
to compare packed decimal values.This
sets the condition codes that can be used in a conditional branch instruction,
as just discussed.Is there any reason
to compare and not then have a conditional branch?

In some
sense, the CLC (Compare Character)
instruction is similar and may be used to compare packed decimal data.However, this use is dangerous, as the CLC
does not allow for many of the standards of standard algebra.

There is
a small problem that arises due to the fact that the decimal point is not
explicitly stored in the packed decimal format.Consider the following addition.

The
positive number 234.12, represented as23
41 2C
is added to the positive number 4.5678, represented as45 67 8C.
The sum might be represented as69
09 0C, which
is not correct.We must keep better
track of the decimal.

It seems
that the best approach is to store all values to be used in a given computation
in the same format, with the same number of implied decimal digits.Assume that the above values are used in
computations in which the most precise data have five decimal digits.Then we would be required to have the
following.

The value
234.12 would be treated as 234.12000, and stored as02 34 12 00 0C.

The value
4.5678 would be treated as 4.56780, and stored as04 56 78 0C.

The sum
will then be correctly stored as 02
38 68 78 0C.

MP: Multiply Packed

This
is of the form OP D1(L1,B1),D2(L2,B2), which provide a 4–bit number
representing the length for each of the two operands.The object code format is as follows.

Type

Bytes

Form

1

2

3

4

5

6

SS(2)

6

D1(L1,B1),D2(L2,B2)

X ‘FC’

L1
L2

B1
D1

D1D1

B2
D2

D2D2

A typical source code example
would be MP
S1, S2.Before the
multiplication, field
S1 holds the multiplicand and field S2 holds the multiplier.After the multiplication, field
S1 holds the product.The rules for the
MP instruction are as follows.

1.Both fields must contain valid packed
data.

2.The maximum length of the first operand is
16 bytes, or 31 digits.However, thisis the maximum length of
the product, not of the multiplicand.See below.

6.The number of digits in the product is
usually equal to the sum of the count of digits in the multiplicand
and the count of digits in the multiplier.

Put another way, prior to
multiplication, for each byte in the multiplier, the field to hold the product
must contain one byte of zero digits to the left of the significant digits that
represent the multiplicand.One
preferred use would be to use the ZAP instruction to move a smaller
multiplicand into the product field, as shown in the illustration below.

Recall
that the assembler does not track the position of the decimal point in any
packed decimal representation.That is
the responsibility of the programmer, who must write assembly language
instructions specifically to correct the product.Consider the example above.A simplistic product might be expressed as 09
80 00 0C.Is this read as
$9,800.00 (a bonus for the worker) or $980.000 (too many decimal places).

In
general, the number of decimal positions in the product is equal to the sum of
the number of decimal places in the multiplier and the number of decimal places
in the multiplicand.If either of these
is zero (or both are zero), no adjustment is required.Otherwise, the number of decimal places in
the product must be adjusted.

The
reason that this adjustment is required is that the number of decimal places is
never tracked, but is always explicit.The only way to be able to assume the number of decimal places in a
numeric representation that does not indicate that number is to have every
arithmetic operation adjust the result to the correct count.

As
an aside, one could write code to track the decimal position explicitly.One might store the above results as pairs of
numbers, such as (1, 400) for hours, (2, 2450) for the rate, etc.However, this is not the standard
approach.What is needed is a way to
truncate a product to the correct number of decimal places; the SRP instruction
does exactly that.

SRP: Shift and Round Packed

The
SRP instruction was designed to shift packed data to the left or right,
effectively dividing or multiplying by a power of ten, and then rounding the
number so produced.The standard use
seems to be a way to round decimal data in the usual fashion; the value 2.416
is rounded to either 2.42 or 2.4 depending on the number of decimals
required.The instruction seems to
support the other option, possibly called “un–rounding”, of extending 2.416 to
2.4160, etc.

While
the SRP instruction can be used with the results of AP, SP, and ZAP; we discuss
it here within the more natural context of MP (multiplication of packed decimal
data).The reason for this choice should
be obvious.The addition of two numbers
with equal counts of decimal places produces a similar result; thus 2.32 + 4.56
= 6.88.On the other hand, if we
multiply 2.32 by 4.56, the result is 10.5792.Depending on the application, it is common to round the result to
something like 10.58, preserving the count of decimal places.

While
on the subject of addition and subtraction, we do not want to overlook an
obvious application of SRP.Consider the
sum 2.416 + 7.32.While this is not
likely to be seen in a standard assembly language program, as the programmer
surely will have been careful to keep all decimal points consistent, it is a
theoretical possibility.In this case,
it would be necessary to use the SRP instruction to convert this to one of the
two equivalent forms: either 2.416 + 7.320 = 9.736 or 2.42 + 7.32 = 9.74.

The
SRP instruction is a storage–to–storage (type SS) instruction, with opcode X‘F0’.Although the SRP is a type SS instruction, it
has three operands.The source code is
commonly written in the form SRP PACKVAL,SHIFTCNT,ROUNDVAL.

Operand 1, here PACKVAL, denotes a
packed field to shifted and possibly rounded.

Operand 2, here SHIFTCNT, indicates
the count of digits to shift.The
maximumshift count is 31, which is the
maximum size of a packed decimal field.

Operand 3, here ROUNDVAL, contains a
single digit (0 – 9) which is to be added to the original value before
shifting.This converts a shift
operation into a rounding.Normally, the values are 0 for left
shifts and 5 for right shifts.

The
use of the rounding value can be seen by an attempt to round the number 2.416
by shifting right one place.A pure
shift would change 2.416 to 2.41, which does have one less decimal place.Use of SRP with a rounding value of 5 would
first convert 2.416 to 2.421 and then shift right to obtain the value 2.42,
considered as a proper rounding of 2.416.

The
SRP operation sets the condition codes to indicate zero, minus, or plus.

The
SRP instruction was not a part of the original S/360 architecture, but was
added with the introduction of the S/370 to replace the MVO (Move with Offset)
instruction.We shall not discuss the
MVO instruction here; the reader is directed to reference R_02 for details.

The
format of the instruction is SRP D1(L,B1),D2(B2),I3.

The
object code format for the SRP instruction is represented in the figure below.

Type

Bytes

Form

1

2

3

4

5

6

SS(1)

6

D1(L,B1),D2(B2),I3

X‘F0’

L I3

B1 D1

D1 D1

B2 D2

D2 D2

L is the length indicator for the
field to be shifted, denoted by PACKVAL in the example above.Remember that the length is a byte count that
is one more than the value stored.Thus,
the single hexadecimal digit can represent a value between 0 and 15 inclusive,
to represent a field length between 1 and 16 inclusive.

I3 is the decimal
digit to be added before shifting.

The
two bytes B1 D1D1 D1 represent the
address of the field to be shifted (PACKVAL ), denoted in the standard
base/displacement form.

The
two bytes B2 D2D2 D2 represent the shift
count, using the standard base/displacement format to represent a count and not
an address.The normal use would be
either to use a register to hold the count, or to set the register field to 0
(indicating no base register) and use the displacement field to hold the
constant value of the shift count.

There
is an interesting feature of this part of the instruction that arises from the
inability of the assembler to process a negative displacement.Recall that the amount shifted is given by a
count in the range 0 through 31.Left
shifts are denoted by positive numbers.It should be obvious that these shift counts can be represented by a
five–bit binary number.

Conceptually,
the right shifts used as a part of rounding are represented by negative numbers
in the range from –1 through –31 inclusive.The actual format of the shift count is dictated by the need to find
another way to represent these negative numbers.

The
best way to view this shift count is as a six–bit two’s–complement signed
integer.
Such a format can represent integers in the range from –32 to +31 inclusive.Some of the more common shift values would
then be stored as follows.

Each
of the values for right shifts can be obtained by calculating the
representation as a
six–bit two’s–complement integer.Consider the value for “3 right”.

The value +3 as a
six–bit binary number00
0011or X’03’.

The one’s complement
of this number11 1100or X‘3C’.

Add
one to this value to get11 1101or X‘3D’.

The
default format for the source code is based on decimal values and not
hexadecimal.Hexadecimal values can be
specifically indicated; e.g., X‘3D’.The easier way is to use a formula:N digits leftencode with the decimal number
N.N digits rightencode with the decimal number (64 –
N).

Examples of the SRP Instruction

In
each of the following examples the value in AMNT2 is being
rounded by adding the value 5 and shifting right two places.The field AMNT2 is assumed to
be at an address specified by the offset 0B2 from the value in base
register 12 (X‘C’).The
first example, showing the use of register 10 (X‘A’) to specify the
shift count, uses an instruction that will be defined later.

In
each of the above instructions (except the first, which is a load register from
halfword), the opcode is X‘F0’, indicating
a SRP instruction.The second byte is to
be viewed as two independent hexadecimal digits.The first digit, with value 4, indicates that the length of the field to be
shifted (AMNT2) is five bytes.The second digit, with value 5, is the value to be added to the field before it is
shifted.The next two bytes (C0 B2) specify the address of the field to be
shifted.The last two bytes specify the
count for the shift.

In
the first example, the count is specified by adding 0 to the value stored in a
register.In the other two, the count is
specified by a constant with no base register.One might use a combination of the two (as in A0 04),
but this usage seems a bit strange.

DP: Divide Packed

The DP (Divide Packed)
instruction divides one packed field (the dividend) by another (the divisor),
producing a quotient and a remainder.The DP instruction is a storage–to–storage instruction, with opcode X‘FD’.The form is OP D1(L1,B1),D2(L2,B2),
which provide a 4–bit number for the length for operand.The object code format is as follows.

Type

Bytes

Form

1

2

3

4

5

6

SS(2)

6

D1(L1,B1),D2(L2,B2)

X ‘FD’

L1
L2

B1
D1

D1D1

B2
D2

D2D2

The lengths and address
calculations are just as in the other packed decimal instructions.The rules for the DP instruction are as
follows.

1.Each
operand must contain data in valid packed decimal format.

2.The
maximum length of the first operand (the dividend) is 16 bytes (31 digits).The maximum length of the
second operand (the divisor) is 8 bytes (15 digits).

3.Either
operand may specify an explicit length.

4.A
zero divisor will cause a program interrupt.

5.DP
uses the normal rules of algebra.Like
signs in the dividend and divisorproduce a positive
quotient; unlike signs produce a negative quotient.

6.After
the division, the field that first contained the dividend now containsthe quotient and remainder,
each with a sign half–byte.

Before division

Dividend

After division

Quotient

Remainder

The remainder field has a size
equal to that of the divisor.Together,
the quotient and remainder occupy the entire dividend field.The address of the quotient is the same as
that for the dividend.The address of
the remainder must be computed.

In
the original operands, the dividend had length (L1 + 1) and the
divisor a length (L2 + 1).In
the results of the operation, the length of the remainder is also (L2
+ 1), the same as that for the divisor.Thus, the length of the quotient is (L1 + 1) – (L2
+ 1) = (L1 – L2), and its length code would be one less:
(L1 – L2 – 1).As
a result, the address of the remainder is given by A(Quotient) + (L1
– L2).

As
is the case with packed decimal multiplication, the program should use the SRP
instruction to adjust the number of decimal places in both the quotient and
remainder.As a general rule the number
of decimal places in the remainder is the same as the number in the divisor,
and the number of decimal places in the quotient is the difference between the
count in the dividend and that in the divisor.If the dividend does not already contain a sufficient number of decimal
places, it is necessary to use the SRP instruction to generate additional
positions by left shifting the dividend.In this case, the value for rounding would be 0.

This
brief discussion of the DP instruction concludes our list of instructions for decimal
arithmetic operations.

Conversion between EBCDIC and Packed Decimal

We have now examined a number of
packed decimal arithmetic instructions.It is now time to face the problem of conversion of digits between
EBCDIC format and packed decimal format.At a later time we shall address the problem of conversion between
packed decimal format and two’s–complement fullword format.

When a number is read from
input, it is presented as a sequence of EBCDIC characters.Arithmetic based on this input must be done
in one of the standard numeric formats, unless one wants to write an
extraordinary amount of support code.The results must then be converted back to EBCDIC and formatted for
output.We now present a number of
instructions used for this purpose.

Along the way, we shall note the
inability of the standard instructions to handle signed data as input.The digits ‘0’ through ‘9’ can be processed,
but the signs ‘+’ and ‘–’ cannot be.We
shall comment on a number of standard tricks that older assembly language
programs use to get around this problem and then write some procedures to
handle the issue.

The main issue in the conversion
between EBCDIC and packed decimal format is suggested by the names of the
operations that can be used for those conversions PACK and UNPACK.In the EBCDIC and zoned decimal format, each
decimal digit requires an 8–bit byte for its representation.In the packed decimal format, each digit
requires a 4–bit hexadecimal digit.This
representation introduces an amusing, but totally unimportant, ambiguity.In a value such as represented by X‘789D’,
are the numeric values decimal or hexadecimal?The answer is that it does not matter, each digit requires four bits for
encoding.

One of the key ideas in
understanding the zoned decimal format is the division of the byte into two
“half bytes” or hexadecimal digits.The
most significant is called the zone part and the least significant is called
the numeric part.The figure below
illustrates this division.

Portion

Zone

Numeric

Bit

0

1

2

3

4

5

6

7

There are two instructions specifically
designed to process these half–byte fields.These are:MVZMove
the zone half byte, andMVNMove
the numeric half byte.

Each of these instructions is a
type SS instruction, more properly classified as character instructions than
packed decimal instructions.The two are
included here because their sole use seems to involve translation to and from
packed decimal format.

The
format of each instruction isOP
D1(L,B1),D2(B2).This format
reflects the fact that each of the source and destination addresses is
specified by a base register (often the default base register) and a
displacement.Here is the format of the
object code.

Type

Bytes

Form

1

2

3

4

5

6

SS(1)

6

D1(L,B1),D2(B2)

OP

L

B1
D1

D1D1

B2
D2

D2D2

The opcode for MVZ is X‘D3’,
that for MVN is X‘D1’.The
instruction is commonly written in source code in the form OP S1, S2.Characteristics of the two instructions
include the following.

1.Each moves half bytes from the address
specified by the second operand to an address specified by
the first operand.

2.Each may move from 1 to 256 half–bytes, as
specified by the length bytein the object code
representation.

3.Neither move affects the contents of the
second operand.

4.All of the addressing conventions used by
the character instruction MVCmay be used with either of
these instructions.

5.Each instruction moves the half–byte
associated with it and doesnot affect the other half
byte.

6.The MVZ (Move Zones) moves the zone
portion of each source byte to the zone portion of the
corresponding destination byte.It does
not change the numeric portion
of the destination byte.

The
MVN (Move Numeric) moves the numeric portion of each source byte to the numeric portion of the
corresponding destination byte.It does
not change the zone portion of
the destination byte.

As we shall soon see, the MVZ
instruction is of more immediate interest to this course, which nevertheless
covers both as important.As always, we
shall illustrate the operation of the instructions by considering two fields
defined by the DC directives.

Assume that we have the following two
data fields defined with initialized storage.

S1DCC‘123’Stored as F1 F2 F3

S2DCX‘45 67 C8’Stored as 45 67 C8

Execute the instruction MVN S2,
S1.This moves the numeric portion of
each byte in
S1 to the numeric portion of the corresponding byte in S2.

F1
F2 F3becomesF1 F2 F345 67 C841 62 C3

Independently, execute the instruction
MVZ S2, S1.This moves the zone portion
of each byte in S1 to the zone portion of the corresponding byte in S2.

F1
F2 F3becomesF1 F2 F345 67 C8F5 F7 F8

We shall jump ahead to mention one good
use of the MVZ instruction, as it applies to the process of unpacking data
using the UNPK instruction.The goal of
the unpacking process is to turn packed decimal data into EBCDIC format
suitable for printing.However, the UNPK
instruction converts from packed decimal format to zoned decimal format.

Consider the positive decimal number
1234, represented in packed decimal format as 01
23 4C.The result of an
unpack instruction will be represented in zoned decimal format as F0
F1 F2 F3 C4, which will print as the string 123D, as X‘C4’
is EBCDIC for ‘D’.

The use of the MVZ instruction is
illustrated by the following.Consider
the following declaration, given in hexadecimal just to make it easier to read.

S3DCX‘F0F1F2F3C4’Stored as F0 F1 F2
F3 C4

The byte X‘C4’ is at location
S3 + 4.The following instruction is
executed.

MVZ S3+4(1),=X‘F0’

In the above instruction, the source
operand is specified as a literal.Note
that the second hexadecimal digit is unimportant.It is the hexadecimal digit F
that occupies the zone part of the byte, and it is only that part that is
moved.

The address associated with the
destination is given by the relative address S3+4; it is four
bytes offset from the address S3.In other words, it is the fifth byte of the
five–byte string.

The (1) part of the
instruction indicates that only one zone in the destination is to be
changed.Here it is the zone part of the
byte at the address S3+4.

The pack instruction is designed
to convert data in zoned decimal format, one digit per byte, to packed decimal
format, with approximately two digits per byte.Due to the similarity of EBCDIC format to zoned decimal format, the instruction
is commonly used to convert from EBCDIC format into packed decimal format.

The PACK instruction is a
storage–to–storage (type SS) instruction, with opcode X‘F2’.
The instruction may be written in source code as PACK PACKED,ZONED.The affect of this instruction is to take the
zoned data in the field represented by the second operand, translate it to
packed format, and place the data into the field represented by the first
operand.

The
instruction is of the form PACK D1(L1,B1),D2(L2,B2), which uses
the standard base/displacement addressing form for each of the two
operands.Note that the length of each
operand (in bytes) is also encoded.The
object code format is as follows.

Type

Bytes

Form

1

2

3

4

5

6

SS(2)

6

D1(L1,B1),D2(L2,B2)

X ‘F2’

L1
L2

B1
D1

D1D1

B2
D2

D2D2

The following are the rules for PACK:

1.Operand
2 must hold data representing digits or blanks, and the rightmost byte musthold the code for a
digit.The coding may be EBCDIC or zoned
decimal.

2.The
maximum length for each operand is 16 bytes.

3.Bytes
referenced by operand 2 are packed one byte at a time from right to left.

4.other
than the rightmost byte, all zones are ignored and only the numeric part of thecode is copied.For the rightmost byte, the half bytes are reversed.The zone part ofthe last byte in zoned decimal
becomes the sign half byte in packed decimal.

Consider
the following two representations of the positive number 123.
As a string of EBCDIC characters, it is the three bytesF1 F2 F3.
As stored in zoned decimal format, it is the three bytesF1 F2 C3.

When
executed according to its original design, the PACK instruction operates on
data in the zoned decimal format.Its
action on this example is shown below.

When the instruction operates on
digital data in EBCDIC form, it functions identically.

Note that the zone part of the
last byte has become the sign half–byte in the packed decimal format.It is for this reason that X‘F’
is recognized as a valid sign indicator.

We now focus on conversions of
decimal data between the two formats that may
be used to represent them:

1.The EBCDIC character encoding used for
input and output.

2.The packed decimal format used for
decimal arithmetic.

Packing Blanks

While the PACK instruction can
handle leading blanks, a serious problem can arise if the field to be packed
contains all blanks (EBCDIC code 0x40).Consider first an acceptable input.Suppose that the five character string “2” or EBCDIC 40
40 40 40 F2
is input.What happens here?Note that the numeric part of the EBCDIC code
for the blank is the same as the numeric part of the EBCDIC code for the digit
“0”.This works, producing the packed string “00002F”,
as illustrated below.

Now consider the five character
input “” or EBCDIC 40
40 40 40 40.This will pack
to the string “000004”, which lacks a valid sign, as shown
below.This invalid packed input cannot
be processed by any packed decimal instruction.

Some authors suggest checking
all input fields and replacing those that are blank
with all zeroes.This suggests a very
common meaning of blanks as equivalent to 0.

Here is the code, directly from
Abel’s textbook.The input field, RATEIN,
is
supposed to contain one to five digits, but no more than five.

CLCRATEIN,=CL5‘ ’Is this a field
of five blanks

BNED50No, it is not
all blanks

MVCRATEIN,=CL5‘00000’ Replace 5 blanks with 5 zeroes

D50PACK RATEPK,RATEINStore packed value in RATEPK

More on Input of Digits to be Formatted as Packed Data

Recall that the input of packed
data is a two–step procedure.

1.Input the digits as a string of EBCDIC
characters.

2.Convert the digits to packed format.

The format of the input is
dictated by the appropriate data declarations.

In this example, we consider the
following declaration of the form of the input, which is best viewed as an
80–column card.Here is a part of a
program to read numbers, one per line.

RECORDIN DS 0CL8080 CHARACTER CARD IMAGE

DIGITSDSCL5FIRST FIVE COLUMNS ARE
INPUT

FILLERDSCL75THE OTHER 75 ARE IGNORED

Here is a properly formatted
input sequence.

1Four blanks before the “1”.

3

13Three blanks before the “13”.

In order to see that this is the proper
format for the digits, we look at a representation that
emphasizes the column placement of the digits.

Reading from right to left:Column 5 is the units columnColumn
4 is the tens columnColumn 3 is the hundreds
column, etc.

Note that each digit is properly
placed; the first line is really 00001.

One Error: Assuming
Free–Formatted Input

Here is some input from the same
program.Recall that it was designed to
read numbers, one per line, and to output the sum..It did
not work.

1

3

13

17

The student expected free–form
input and assumed that this would be interpreted as the sum
1 + 3 + 13 + 17 = 34.But free–form
input is an artifact of a well–written run time system, with particular
attention to the user interface.

Here is the way that the input
was interpreted.

To me this looks like 10000
+ 30000
+ 13000 + 17000.I had expected the above input to give a sum
of 70000.It did not.Here is the code loop for the processing
routine.

B10DOITMVC DATAPR,RECORDINFILL THE PRINT AREA

PUT PRINTER,PRINTSTART THE PRINT

PACK PACKIN,DIGITSINCONVERT INPUT TO DECIMAL

APPACKSUM,PACKINADD IT UP

BRR8RETURN FROM
SUBROUTINE

Here is the actual output.All we get is the header line and a print
echo of the first line input.The header
line had been printed by an earlier part of the program.

***PROGRAMFOURCSUSPRING2009 ***********

1

A Diagnostic

Here is the code that isolated
the problem.Note the one line commented
out.

B10DOITMVC DATAPR,RECORDINFILL THE PRINT AREA

PUT PRINTER,PRINTSTART THE PRINT

PACK PACKIN,DIGITSINCONVERT INPUT TO DECIMAL

***APPACKSUM,PACKINADD IT UP

BRR8RETURN FROM
SUBROUTINE

The program ran to
completion.Here is the output for the
code fragment above.

************** TOP OF DATA
*****************************

***PROGRAMFOURCSUSPRING2009 ***********

1

3

13

17

THE SUM = 000000

************
BOTTOM OF DATA ****************************

The Diagnosis

Look again at the input.

The first line, as EBCDIC
characters is read as follows.F1
40 40 40 40

The PACK command processes right
to left.It will process any kind of
data, even data that do not make sense as digits.This input will pack to X‘10004’, an invalid
packed format.

With no valid sign indicator,
the AP instruction fails and the program terminates.

Printing Packed Data

In order to print packed decimal
data, it must be converted back to a string of EBCDIC characters.The UNPK command is a part of this
conversion.It converts digital data
from the packed decimal form to the zoned decimal form, which must be processed
further.

The UNPK instruction is a
storage–to–storage (type SS) instruction, with opcode X‘F3’.
The instruction may be written in source code as UNPK ZONED,PACKED.The affect of this instruction is to take the
packed data in the field represented by the second operand, translate it to
zoned decimal format, and place the data into the field represented by the
first operand.

The
instruction is of the form UNPK D1(L1,B1),D2(L2,B2), which
uses the standard base/displacement addressing form for each of the two
operands.Note that the length of each
operand (in bytes) is also encoded.The
object code format is as follows.

Type

Bytes

Form

1

2

3

4

5

6

SS(2)

6

D1(L1,B1),D2(L2,B2)

X ‘F3’

L1
L2

B1
D1

D1D1

B2
D2

D2D2

The following are the rules for PACK:

1.The
maximum length for each field is 16 bytes, which implies a maximum lengthof 8 bytes for the field
holding the packed data.Suppose that
the packed data is stored in 9 bytes, which would
represent 17 digits.This would unpack
to 17 bytes.

2.Bytes
referenced by operand 2 are unpacked right to left, one byte at a time.

3.For
all but the rightmost byte of the packed data, each hexadecimal digit is
handled separately, being inserted
into the numeric zone of the zoned data format.

4.The
rightmost byte of the packed data has its half bytes reversed, with its sign half byte being moved to the
zone part of the zoned data and the left half bytebeing moved to the numeric
part of the zoned data.Consider the
number 47, which would be represented
internally as 04 7C.

When this is unpacked, we might
want it to become F0
F4 F7, which would print as the three–digit string “047”
or perhaps as the two–digit string “47”.However, UNPK just swaps the sign half byte
to produce F0 F4 C7.

This prints as “04G”,
because X‘C7’
is the EBCDIC code for the letter ‘G’.

We have to correct the zone part
of the last byte.The problem occurs
when handling the sign code, “C” or “D” in the Packed Decimal
format.This occurs in the rightmost
byte of a packed decimal value.

Printing Packed Data
(Part 2)

Here is the code that works for
five digit numbers.It is written as a subroutine,
that is called as BALR R8,NUMOUT.

NUMOUTCPQTYPACK, =P‘0’IS THE NUMBER NEGATIVE

BNMNOTNEGNO, IT IS NOT.

MVIQTYOUT+5,C‘-’YES,
IT IS. PLACE SIGN AT QTYOUT+5

NOTNEGUNPK QTYOUT,QTYPACKPRODUCE FORMATTED NUMBER

MVZQTYOUT+4(1),=X’F0’MOVE 1 BYTE TO ADDRESS QTYOUT+4

*THIS SETS THE ZONE PART CORRECTLY

BR 8RETURN ADDRESS IN REGISTER 8

QTYPACKDS PL3HOLDS FIVE DIGITS IN THREE
BYTES

QTYOUTDS 0CL6

DIGITSDS CL5THE FIVE DIGITS

DC CL1’ ’THE SIGN

Again, the expression QTYOUT+4 is an address, not a value.

If QTYOUT holds C‘01234’,
then QTYOUT+4
holds C ‘4’.

Here, we have accidentally introduced
the standard simplistic way of representing negative numbers in the printout of
an assembly language program.This is
done because it is far simpler than formatting the output in the standard
manner, in which the minus sign is to the left of the most significant digit in
the output.The table below will
illustrate the two output options as might be seen for a five–digit number.

Internal Value

Standard Print Format

Simple Print Format

01
23 4C

1234

01234

01
23 4D

-1234

01234-

Unpacking and Editing
Packed Decimal Data

Each of the UNPK (Unpack) and
the ED (Edit) instruction will convert packed decimal data into a form suitable
for printing.The ED and EDMK
instructions seem to be more useful than the UNPK.In addition to producing the correct print representation
of all digits, each allows for the standard output formats.

The ED instruction is a
storage–to–storage (type SS) instruction, with opcode X‘DE’.
The instruction may be written in source code as ED PRNTREP,PACKED.

The EDMK instruction is also a
storage–to–storage (type SS) instruction, with opcode X‘DF’.It may be written in source code as EDMK
PRNTREP,PACKED.

Each instruction is of the form OP
D1(L1,B1),D2(L2,B2), which uses the standard base/displacement
addressing form for each of the two operands.Note that the length of each operand (in bytes) is also encoded.The object code format is as follows.

Type

Bytes

Form

1

2

3

4

5

6

SS(2)

6

D1(L1,B1),D2(L2,B2)

OP

L1
L2

B1
D1

D1D1

B2
D2

D2D2

The use of the ED instruction is a
two–step process.

1.Define an edit
pattern to represent the punctuation, sign, and handling of leading zeroes that is
required.Use the MVC instruction to
move this into the output position, which is PRNTREP
in the above example.

2.Use
the ED instruction to overwrite the output position with the output string that
will be formatted as specified by
the edit pattern.The first character in
the editpattern is a fill character
that is not overwritten.

The EDMK
instruction is identical to the ED instruction, except that it “marks” the
leftmost significant digit by returning its address as the contents of
general–purpose register 1.Think of the
print output being scanned left to right, towards increasing byte
addresses.The most significant digit is
the leftmost.We shall discuss this more
thoroughly in just a bit.

Here is an example.Note that there are a number of length
constraints, specifically that the length of the edit pattern match the length
of the output area.

MVCCOUNPR,=X‘40202020’Four bytes
of pattern

EDCOUNPR,COUNT

More
code here

COUNTDCPL‘001’

COUNPRDSCL4

Note the sequence of events
in these two lines of code.

1.The edit pattern
is moved into the output field.The
leading pair of hexadecimal digits, 0x40, state that a
blank,‘ ’, will replace all leading zeroes.

2.The
decimal value is edited into the output field COUNPR, overwritingthe edit pattern.

The
result is printed as the four character sequence “1”, represented in EBCDIC
as X‘4040
40F1’.

ED: Basic Rules

The basic
form of the instruction isED
S1,S2

The first
operand, S1, references the leftmost byte of the edit word, which has been
placed in the output area.This field
will be filled with the formatted output.

The
second operand, S2, references a packed field to be edited.

One key
concept in the editing for output is called “significance”.In many
uses, leading zeroes are not treated as significant and are replaced by the
fill character.

Thus, the
number represented in packed decimal format as 001C might print as “1” or as “001” depending on
whether or not leading zeroes are required.

There are
times in which one wants one or more leading zeroes to be printed.As an
example, consider the real number 0.25, which is stored as 025C.It might best be
printed as “0.25” with at least one leading zero.This leads to the concept called “forcing significance”, in which
leading zeroes are printed.

The Fill Character

The leftmost
hexadecimal byte in the output area before the execution of the instruction
begins represents the fill character to use when replacing non–significant
leading zeroes.Two standard values are:X‘40’a blank‘ ’X‘5C’an asterisk‘*’Often used in check printing.

Consider
the three digit number 172, stored internally as 172C.For now, assume that
the field from which it will be printed allows for five digits.With a fill character of X‘40’ (blank), this
would normally be printed as 172.

We can force
significance to cause either 0172 or 00172 to be
printed.For this number,
with a fill character of X‘40’, our options would be one of
the three following.

1720172
00172

With a
fill character of X‘5C’, we might have one of the
three following.Note that the function
of the leading “*” is to prevent other digits from being inserted at
the left.

**172
*0172
00172

By itself, the leading asterisk is an
inadequate security feature.However,
when combined with other printing conventions (noted below), it can prevent
many obvious ways of altering the amount of a check.

An amount on a properly printed check
might appear as $**1,234.00.

The Edit Word:
Encountering Significance

Here are
some of the commonly used edit characters.Note that it is more convenient
to represent these by their hexadecimal EBCDIC.

One key
idea is the encounter of significance.The instruction generates digits for possible
printing from left (most significant) to right (least significant).Two events cause this encounter: 1) a
non–zero digit is generated, and 2) a digit is encountered that is associated
with the 0x21 edit pattern.As noted
above, the first character in the edit word is the fill character.The codes that are used for the digit
positions are as follows:

0x20Digit selector.This represents a digit to be printed, unless ithappens
to be a leading non–significant zero.In
that case, the fill character is printed.

0x21Digit selector and significance starter.This not only represents adigit
to be printed, but it also forces significance.Each digitto the
right will be printed, even if a leading zero.

Unless
one is careful, ED might result in an output field that is all blanks.For printing integer values, one might
seriously consider ending the edit pattern with the values 0x2120.Significance is forced after the next–to–last
digit, forcing at least one digit to be printed.

As noted
above, the EDMK instruction will insert the address (not the offset) of the
leftmost significant digit into general–purpose register 1.This address can be decremented by 1 and then
used to place a currency sign or other prefix.Please see the example below.

The Edit Word: Formatting the Output

Part of
the function of the ED and EDMK commands is to
allow standard formatting of the output, including decimal points and
commas.Handling of negative numbers is
a bit strange.

Here are
the standard formatting patterns.

0x4BThe decimal point.If significance has been encountered, the
decimal point
is printed.Otherwise, the fill
character is printed.

0x6BThe comma.If significance has been encountered, the comma isprinted.Otherwise, the fill character is printed.

0x60The minus sign, “–”.This is used in an unexpected way.

The
standard for use of the minus sign arises from conventions found in commercial use.The minus sign is placed at the end of the number.

Thus the
three digit positive number 172 would be printed as172
and the three digit negative number –172 would be printed as172–.

The edit
pattern for this output (ignoring the significance issue) would be as follows:

0x4020202060.
The fill character is a
blank.There are three digits followed
bya
sign field, which is printed as either “–” or the fill character.

ED: An Example with
Formatting

In this
example, it is desired to print a seven digit number, formatted as follows.

1.It
is a fixed point number, with two digits to the right of the decimal.

2.It
has five digits to the left of the decimal and places a comma in the standard location if
significance has been encountered.

3.It
will be printed with a terminating “–” if the number is negative.

This
situation is illustrated in the following graphic.

The edit pattern
for this example would be as follows:

1

2

3

4

5

6

7

40

20

20

6B

20

21

20

4B

20

20

60

Note:The
significance forcer at digit 4 will insure that digit 5 is printed,even if it is a zero.

EDMK: An Example

Here we
shall give an example of the use of the Edit and Mark instruction, using the
edit word that we have just discussed.Here is the sample code:

MVCAMTPR,EDPATMOVE EDIT PATTERN
TO PRINT FIELD

EDMK AMTPR,AMTPAKFORMAT THE PACKED FOR PRINTING

*

*HERE REGISTER 1 CONTAINS THE BYTE
ADDRESS OF THE MOST

*SIGNIFICANT DIGIT.THE ADDRESS IS NOT LESS THAN

*(AMTPR + 1), THE ADDRESS OF “DIGIT 1”
IN THE PATTERN ABOVE.

*

SH R1,=H‘1’DECREMENT ADDRESS BY 1

MVI 0(1),C‘$’PLACE THE DOLLAR SIGN

EDPATDC
X‘4020206B2021204B202060’THE PATTERN
ABOVE

AMTPAKDC P‘12345’THE AMOUNT TO DISPLAY

AMTPRDS CL11THE PRINT REPRESENTATION

If the value in AMTPAK were formatted with the ED instruction,
we would not be able to use the code above to place the “$” character.Here are the two outputs.

With the ED operator, the output is$123.45

With the EDMK instruction, the
output is $123.45

ED:More on the “*” Fill Character

One option
for the fill character is 0x5C, the asterisk.Why is this used?Consider the above seven–digit example, in which
the number is to be viewed as a money amount.We shall use the dollar sign, “$”, in the amount.

Consider
the amount $123.45.We
would like to print it in this fashion, but placing the dollar sign in this way
presents difficulties.Standard coding
practice would have been to place the dollar sign in a column just prior to
that for the digits.The format would
have been as follows.

Column

0

1

2

3

4

5

6

7

8

9

10

$

Digits

,

Digits

.

Digits

–

If the blank fill character were
chosen, this would print as$123.45.
Note the spaces before the first digit.To prevent fraud, we print$***123.45

ED: A More Complete
Example

We now
show the complete code for producing a printable output from the seven digit
packed number considered above.We shall
use “*” as a fill character.Note that
the output will be eleven EBCDIC characters.Here is the code.

PRINTAMT
MVC AMNTPR,EDITWD

EDAMTPR,AMTPACK

*The fill character is “*”.Also punctuation as follows,.-

EDITWDDC X‘5C20206B2021204B202060’

*

AMTPACKDS PL4FOUR BYTES TO STORE SEVEN DIGITS.

AMTPRDS CL11THE FORMATTED PRINT OUTPUT

ED:Another Example Using an Edit Pattern

This
example is adapted from Abel’s textbook.Suppose that we have the following.

The
packed value to be printed is represented by DCPL3‘7’This is represented as 00 00 7C.

The edit
pattern, when placed in the output area beginning at byte address 90,
is as shown below.

Address

90

91

92

93

94

95

96

97

Code

40

20

21

20

4B

20

20

60

Note the
structure here:3 digits to the
left of the decimal (at least one will be printed),

the decimal point,
and

two
digits to the right of the decimal.

This
might lead one to expect something like “000.07” to be printed.

At
address 90the contents are
0x40, assumed to be the fill character.This
location is not altered.

Address

90

91

92

93

94

95

96

97

Code

40

20

21

20

4B

20

20

60

At address 91the contents 0x20 is a digit selector.The first digitof the
packed amount is examined.It is a 0.00007CED
replaces the 0x20 with the fill character, 0x40.

Address

90

91

92

93

94

95

96

97

Code

40

40

21

20

4B

20

20

60

At address 92the contents 0x21 is a digit selector and a
significance forcerfor
what follows.The second digit 00007Cof the
packed amount is of the packed amount is examined.It is
a 0.ED replaces the 0x21 with the fill
character, 0x40.

Address

90

91

92

93

94

95

96

97

Code

40

40

40

20

4B

20

20

60

At address 93the contents 0x20 is a digit selector.Significance has beenencountered.The third digit of the packed 00007Camount
is of the packed amount is examined.It is
a 0.ED replaces the 0x20 with 0xF0, the
code for ‘0’.

Address

90

91

92

93

94

95

96

97

Code

40

40

40

F0

4B

20

20

60

At address 94the
contents 0x4B indicate that a decimal point is to be printedif
significance has been encountered.It has
been, so the patternis not
changed.Had significance not been
encountered, thiswould
have been replaced by the fill character.

Address

90

91

92

93

94

95

96

97

Code

40

40

40

F0

4B

20

20

60

At address 95the contents 0x20 is a digit selector. Significance has beenencountered.The fourth digit of the packed 00007Camount
is of the packed amount is examined.It is
a 0.ED replaces the 0x20 with 0xF0, the
code for ‘0’.

Address

90

91

92

93

94

95

96

97

Code

40

40

40

F0

4B

F0

20

60

At address 96the contents 0x20 is a digit selector.Significance has beenencountered.The fourth digit of the packed 00007Camount
is of the packed amount is examined.It is
a 7.ED replaces the 0x20 with 0xF7, the
code for ‘7’.

Address

90

91

92

93

94

95

96

97

Code

40

40

40

F0

4B

F0

F7

60

At address 97the
contents 0x60 indicate to place a minus sign if the numberto be
printed is found to be negative.It is
not, so the instructionreplaces
the negative sign with the fill character.

Address

90

91

92

93

94

95

96

97

Code

40

40

40

F0

4B

F0

F7

40

At this point, the process terminates.We have the EBCDIC representation of
the string to be printed.As characters,
this would be “0.07 ”.Note that there is a trailing space in this
printout; it occupies a column in the listing.

Note that additional code would
be required to print something like “ $ 0.07 ”.
This would involve a scan of the output of the ED instruction and placing the
dollar
sign at a place deemed appropriate.

Suppose
now that the packed value to be printed is represented by DCPL3‘7’This is represented as 00 00 7D.

Suppose
that the edit pattern is specified as follows:

Address

90

91

92

93

94

95

96

97

Code

5C

20

21

20

4B

20

20

60

The reader should verify that the print
representation would be “***0.07-”.