|
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.
|
|