Numbers


The S/370 architecture provides several ways to represent numbers:

Floating Point
Packed Decimal
Character and
Binary Integer

This section covers the most fundamental numeric representation, Binary Integers.

A more formal presentation of some of this material is provided at the beginning of POPs Chapter 7, General Instructions, as well as some information on the other numeric representations. Further information on Packed Decimal numbers appears at the beginning of POPs Chapter 8, Decimal Instructions. The Floating Point numbers are likewise described at the beginning of POPs Chapter 9, Floating-Point Instructions.

Binary, Decimal, Octal, and Hexadecimal

Binary, Decimal, Octal, and Hexadecimal

These formats (Binary, Octal, Decimal, and Hexadecimal) are really just names for a particular instance of the mathematical concept called "base". Please do not confuse the mathematical "base" concept with the S/370 "base register" concept. Here, when we mention the word "base", we will be referring to the mathematical concept. Let's begin by defining our terms, in a less than rigorous mathematical way. If you want rigorous mathematics, you're in the wrong tutorial.

A digit is a visual representation (a symbol) of a numeric value, such that any digit is an integer (whole number) which is always less than the "base" in which that numeric value occurs. Digits in the most commonly seen base, base 10 (called decimal), are one of the ten Arabic number symbols: 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9. Hexadecimal (base 16) utilizes the letters A, B, C, D, E, or F to represent digits greater than ten.

Hexadecimal
Decimal
Octal
Binary
0
0
0
0000
1
1
1
0001
2
2
2
0010
3
3
3
0011
4
4
4
0100
5
5
5
0101
6
6
6
0110
7
7
7
0111
8
8
10
1000
9
9
11
1001
A
10
12
1010
B
11
13
1011
C
12
14
1100
D
13
15
1101
E
14
16
1110
F
15
17
1111

You can think of Binary as being "based on" the number 2, Octal as being "based on" the number 8, Decimal as being "based on" the number 10, and Hexadecimal as being "based on" the number 16. The following table shows the relationship between Name, Base, and Digits.

Name
Base
Digits
Binary
2
0 1
Octal
8
0 1 2 3 4 5 6 7
Decimal
10
0 1 2 3 4 5 6 7 8 9
Hexadecimal
16
0 1 2 3 4 5 6 7 8 9 A B C D E F

To represent numeric values larger than the Base, additional digits (in the range constrained by the base) will appear to the left of prior digits. In the following examples, leading zeros appear to help visually align the numbers; they serve no other purpose.

In Binary, we count:

0000, 0001,
0010, 0011,
0100, 0101,
0110, 0111,
1000, 1001,
1010, 1011,
1100, 1101,
1110, 1111,

In Octal, we count:

00, 01, 02, 03, 04, 05, 06, 07,
10, 11, 12, 13, 14, 15, 16, 17,
20, 21, 22, 23, 24, 25, 26, 27

In Decimal, we count:

00, 01, 02, 03, 04, 05, 06, 07, 08, 09,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29

In Hexadecimal, we count:

00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 2A, 2B, 2C, 2D, 2E, 2F

Let's point out some interesting things about these numbers. First, notice how many places it takes to represent a Binary number as opposed to a Hexadecimal number. Next, notice how the numbers in each base range from zero to (base number minus one). Finally, notice that when we get to the base number that we add a new digit on the left, just as you are used to when counting in decimal.

The numbers zero through 255 appear in various formats (Decimal, Hexadecimal, and Binary) in the Code Translation Table of the S/370 Reference Summary (REFSUM).

Powers of Two

Experienced assembler programmers usually recognize the following binary, decimal and hexadecimal equivalents because the "one" bit is just shifted over one (binary) place. In the binary column, a space is introduced to aid pattern recognition.

Hexadecimal
Decimal
Binary
2n
01
1
0000 0001
20
02
2
0000 0010
21
04
4
0000 0100
22
08
8
0000 1000
23
10
16
0001 0000
24
20
32
0010 0000
25
40
64
0100 0000
26
80
128
1000 0000
27

Two comments about the above table. First, when you want to use a byte of main storage to contain a set of flags, the above values (stated in hexadecimal, decimal, or binary as you prefer) are the values of each flag bit.

Second, this table is also a table of Powers of Two, such as appears in the REFSUM. Our table gives the first eight Powers of Two, which are missing from the REFSUM. The REFSUM didn't bother to include the first eight Powers of Two because they are so commonly known, and they were short on space. In case you don't deal with raising numbers to a power every day, by definition any number raised to the zeroth power equals one.

Powers of Sixteen

Below is a Powers of Sixteen table for your reference. As we did with Binary numbers, we insert spaces to make the pattern clear. We also show the equivalent hexadecimal number.

Hexadecimal
Decimal
16n
00 00 00 01
1
160
00 00 00 10
16
161
00 00 01 00
256
162
00 00 10 00
4 096
163
00 01 00 00
65 536
164
00 10 00 00
1 048 576
165
01 00 00 00
16 777 216
166
10 00 00 00
268 435 456
167

Bits, Nibbles, and Bytes

Although it might not look like it at first glance, Binary numbers and Hexadecimal numbers are closely related.

In the S/370 architecture, each Binary digit occupies one bit in main memory.

Each Hexadecimal digit can be viewed as though it were composed of four Binary digits. These four bits are sometimes called a "nibble".

Two Hexadecimal digits occupies a byte (8 bits).

This grouping of four Binary digits, or one Hexadecimal digit, is actually a pun: a nibble is half a byte.

S/370 Assembler Notation

Although subscripts are normally used to indicate the base of a number, such as 19710, 10012, or 2CE16 subscripts are a problem in normal text such as S/370 assembler source code.

To solve the problem, the S/370 assembler introduces some notational conventions which it recognizes in lieu of subscripts. There are a wealth of such notations, but we will only cover two here: one notation for Binary, and one notation for Hexadecimal.

Binary numbers are framed with B'xxxx'. The Binary number 1001 is thus represented by B'1001'.

Hexadecimal numbers are framed with X'xxxx'. The Hexadecimal number 2D4F is thus represented by X'2D4F'. Some of you might know the C language, and the same number would be represented by 0x2D4F in C source code; the S/370 Assembler won't understand the 0x notation.

Leading zeros are not required for either Binary of Hexadecimal numbers.

Converting Numbers

Since we normally think in Decimal, we might like to be able to convert Binary or Hexadecimal numbers to Decimal. Most programmers use a calculator (software or hardware) to perform these conversions, but we cover the technique so you can understand how it works.

Converting Hexadecimal to Decimal

Given a hexadecimal number X'52EC', convert it to decimal.

The first technique we show here is summarized in the REFSUM in the "Hexadecimal and Decimal Conversion" section.

There are four nibbles in the number X'52EC'. Use each of these nibbles to index into the "Hexadecimal Columns" matching the nibble's place.
Begin with the rightmost nibble X'C', begin with column 1; locate the nibble's value in column 1; the value is 12.
Move left to the next nibble X'E', and move to column 2; locate the nibble's value in column 2; the value is 224.
Move left to the next nibble X'2', and move to column 3; locate the nibble's value in column 3; the value is 512.
Move left to the next nibble X'5', and move to column 4; locate the nibble's value in column 4; the value is 20480.
Total the numbers: 12 + 224 + 512 + 20480 = 21228.

The same technique, when viewed mathematically is:

52EC16 = (516 * 100016) + (216 * 10016) + (E16 * 1016) + (C16 * 116)

Converting the nibble portion of each term from base 16 to base 10 is as simple as looking up the nibble's value in the Hexadecimal,Decimal, Octal, and Binary table we showed at the beginning of the page:

52EC16 = (510 * 100016) + (210 * 10016) + (1410 * 1016) + (1210 * 116)

All that leaves in base 16 are what we now reveal are Powers of 16. There's a table of them in the REFSUM, but we show our work below.

For your reference, we show some equivalences:
100016 = 163 = 16 * 16 * 16
10016 = 162 = 16 * 16
1016 = 161 = 16
116 = 160 = 1

From here on, all we have to do is normal multiplcation and addition in base 10, with which we all should be familiar.

52EC16 = (510 * (16*16*16)10) + (210 * (16*16)10) + (1410 * (16)10) + (1210 * 110)

52EC16 = (510 * 409610) + (210 * 25610) + (1410 * 1610) + (1210 * 110)

52EC16 = (2048010) + (51210) + (22410) + (1210)

Before we show the final result, take note of the prior method using the Hexadecimal Columns table in the REFSUM; our numbers match.

52EC16 = 2122810

The deeper insight here is that each nibble of a hexadecimal number (beginning on the right end, moving right to left) advances to the next Power of 16 (beginning with 160 = 1).

Converting Decimal to Hexadecimal

The only technique we show here is also summarized in the REFSUM in the Hexadecimal and Decimal Conversion section. Mathematically, all we're doing is repeatedly dividing and subtracting, just like when you do "long division" in base 10. The REFSUM makes the division part easy since they supply the Hexadecimal Columns table.

Given a decimal number 21228, convert it to hexadecimal.

Begin with the entire decimal number 21228; locate the largest decimal number value in the table that is not larger than 21228, which is 20480; look to the left of 20480, and see the hexadecimal number 5, which resides in Hexadecimal Column 4; retain the hexadecimal number 5, representing X'5000'

Subtract X'5000' = 20480 from 21228, giving 744; locate the largest decimal number value in the table which is not larger than 744, which is 512; look to the left of 512, and see the hexadecimal number 2, which resides in Hexadecimal Column 3; retain the hexadecimal number 2, representing X'200'

Subtract X'200' = 512 from 744, giving 232; locate the largest decimal number value in the table which is not larger than 232, which is 224; look to the left of 224, and see the hexadecimal number E, which resides in Hexadecimal Column 2; retain the hexadecimal number E, representing X'E0'

Subtract X'E0' = 224 from 232, giving 12; locate the largest decimal number value in the table which is not larger than 12, which is 12; look to the left of 12, and see the hexadecimal number C, which resides in Hexadecimal Column 1; retain the hexadecimal number C, representing X'C'

Subtract X'C' = 12 from 12, giving zero; we have now accumulated all the hexadecimal digits we need, simply string them together in the order in which they were located, left to right: 52EC.

Dealing with Binary

While it would also be possible to use the same techniques to convert between Binary and Decimal, there is a much simpler technique. Recall we said that each Hexadecimal nibble was the equivalent of four Binary digits. Converting from Hexadecimal to Binary is as simple as treating the corresponding four Binary digits as a text string that replaces each Hexadecimal nibble, like so (spaces are provided in the binary string to make the relationship clear):

X'52EC' = B'0101 0010 1110 1100'
            5    2    E    C
Going the other way from Binary to Hexadecimal is just as simple.
B'1000 0100 0010 0001' = X'8421'
  8    4    2    1
Thus to convert from Decimal to Binary, or from Binary to Decimal, all we need to do is convert from Decimal to Hexadecimal, or Hexadecimal to Binary and apply the text string replacement technique.