"A floating point subroutine package for the 1802"
Paul Wasserman, Union NJ
published issue #37 Vol 4, 1979, pages 17-19 including hex dump.
"Reprint Privileges: Article herein that are copyrighted by
individual authors or otherwise explictly marked as having
restricted reproduction rights may not be reprinted or copied
without permission from People's Computer Company, or the
authors. All other articles may be reprinted for any non-com-
mercial purpose, provide a credit-line is included. The credit-
line should indicate that the material was reprinted from "Dr.
Dobb's Journal of Computer Calisthenics and Orthodontia,
Box E, Menlo Park, CA 94025" - end quote.
After purchasing my 1802 based microcomputer system,
I was surprised to find how little software there is available
for it. In particular, I was disappointed by the absence of a
readily-available ﬂoating point arithmetic subroutine package.
To help wipe out this void, I set out to write such a subroutine
package. The results of my work appear in the rest of this
article.
When this project was started, I decided that the ﬂoating
point arithmetic routines would implement a set of existing
algorithms rather than writing a new set. Suitable algorithms
were found in a book written by Neill Graham entitled "Micro-
processor Programming for Computer Hobbyists", published
by Tab Books. I strongly recommend the purchase of this
book to anyone who wishes to understand or modify the
intemal workings of this set of ﬂoating point arithmetic
routines. This article will not attempt to describe the routines’
inner workings. It will, however, provide the information
needed to use these routines.
All ﬂoating point numbers contain two parts: a signed
mantissa and a signed exponent. +1.16 X 10**+2 is an example
of a decimal ﬂoating point number. +1.16 is the signed
mantissa and +2 is the signed exponent. Similarly, +1.1101 X
2**+110 is the binary ﬂoating point equivalent of 116. Here,
+l.1101 is the signed mantissa and +110 is the signed
exponent. The binary mantissa used by the ﬂoating point
subroutine is 32 bits long (4 bytes). The radix point lies
between the left-most bit (LMB) and the bit to the immediate
right of the LMB. The sign of the mantissa is represented by a
single byte which can take on two values, 00(hex) or FF
(hex). If this byte is 00 (hex), the mantissa is positive.
Similarly, if this byte is FF (hex), the mantissa is negative.
The signed binary exponent is represented by a single byte.
In order to have both positive and negative integers in the
single byte exponent, a convenient numbering scheme was
adopted. This scheme deﬁned 80 (hex) as zero. Anything
larger than 80 (hex) is positive and anything smaller than
80 (hex) is negative. For example, 83 (hex) represents a binary
exponent of +11 = +3 (decimal) and similarly 7F (hex) repre-
sents a binary exponent of -1 . The exponent can vary between
00 (hex) and FF (hex). These numbers represent decimal
exponents between the range of 10**-39 and 10**+38.
Figure l - mantissa is always .MMMM. Byte addresses are
in representation order.
AC Sign .AC Mantissa AC exp
010D 103,102,101,100 010F,010E
OP Sign .OP Mantissa OP exp
0110 107,106,105,104 0111
Figure 1
illustrates the representation of ﬂoating point numbers in the
accumulator (AC) and operand (OP) registers. Notice that the
accumulator exponent is 2 bytes wide. The hi byte is O0 (hex)
unless an over or underﬁow has occurred. The hexidecirnal
numbers placed below the diagrams in Figure 1 are the
memory locations used to store (in RAM) the bytes that make
up the accumulator and operand.
Most people can handle ﬂoating point decimal numbers
with relative ease. The computer, unlike most people, is more
efﬁcient at handling binary numbers. To accommodate this
difference, two routines are included in the ﬂoating point
arithmetic package which allow for the conversion between
binary and decimal numbers. Both of these routines use the
accumulator register to hold binary numbers. An additional
register is used by both routines for decimal numbers. This
decimal register (D) is shown in Figure 2.
Figure 2 decimal point is at right end of mantissa.
DM sign DM mantissa.
0114 0115,116,117,118,119,11A,11B.
DE sign DE exp
011C 011D,11E
The decimal register
is composed of four parts: the sign of the mantissa (DM Sign),
the 7-digit decimal mantissa (DM), the sign of the exponent
(DE Sign) and the 2-digit exponent (DE). Both signs are
represented by their standard ASCII codes; that is, 2D (hex)
for negative and 2B (hex) for positive. The decimal digits
(0-9) of both the exponent for the mantissa are represented
by their corresponding 4-bit binary codes. These codes are
placed in the four least signiﬁcant bits of each byte. The four
most signiﬁcant bits are ignored by the conversion routines.
This allows the use of ASCII codes on all entries in decimal
register. For example, the number +1.234567 X 10” =
+1234567. X 10**+2 could be represented in the decimal register
in the following ways: 2B 01 02 03 04 05 06 07 2D 00 04 or
2B 31 32 33 34 35 36 37 2D 30 34 (ASCII).
These conversion routines appear in Figure 3 as D—>AC
(decimal to binary conversion) and AC —> D (binary to deci-
mal conversion).
All the routines in the floating point arithmetic package
use the Standard Call and Return Technique (SCRT). This
technique is explained in RCA’s User Manual for the CDP
1802 [MPM-201] on pgs. 61-64.
[Note by Herb: SCRT establishes:
R2 is stack pointer to stack area
stack is push and decrement addr, pop and increment addr
R3 is program counter
R4 is call as in SEP R4 [address]
R5 is return as in SEP R5
R6 is pointer to (address) after the called address,
which may have additional data/argument ]
The microprocessor registers R(2)—
R(6) must be set up to handle the SCRT before any sub-
routines can be used. The user must also provide the SCRT
code before using any subroutines. A subroutine is called by
a D4 (hex) instruction, followed by the address of the sub-
routine. In some cases, additional numbers (labeled arguments
in Figure 3) follow the address. Figure 3 lists all the user
subroutines in the ﬂoating point arithmetic package.
[Figure 3: list of routine calls. Addresses preceeded by 1802
code D4 (SEP R4) which is SCRT CALL . V is a variable
register numbered 00H to 29H. Calling code is detailed in
the text.]
0400 AC+OP -> AC
02E9 AC-OP -> AC (address corrected from original article)
02B7 AC*OP -> AC
034C AC/OP -> AC
03C3 0 -> AC
03D9 0 -> OP
0773 SQRT(AC) -> AC
0500 D -> AC
0598 AC -> D
06DA V -> AC
0705 V -> OP
072C AC -> V
0754 MMMMSE -> AC
The top four routines shown in Figure 3 perform ﬂoating
point addition, subtraction, multiplication and division, res-
pectively. The next two routines clear (set to zero) the con-
tents of the accumulator or the operand. A square root routine
follows next on the list. This routine uses the Newton-Raphson
iterative method to ﬁnd the square root of the contents of
the accumulator. The next two routines perform conversions
between binary and decimal numbers as previously described.
The next three routines allow the user to store and recall
[variable] numbers from memory. [The last stores a constant
into the accumulator.]
There are forty-two variable storage
registers (referred to as variables) numbered 00(hex)-29
(hex). Any one of these variables can be loaded into either the
accumulator or operand registers. Similarly, the contents of
the accumulator can be stored in any one of the variables. For
example, if we wanted to load the accumulator with the con-
tents of variable 08, the following code would be used D4
06DA 08 (08 = V).
The last routine shown in Figure 3 loads
the accumulator with the binary ﬂoating point number that
immediately follows the instruction. The ﬁrst four bytes fol-
lowing the calling address (0754) make up the binary mantissa.
These bytes should be in reverse order. For example, if the
mantissa equals 42 6C 3D 0E, this subroutine requires 0E, 3D,
6C, 42 be placed after the calling address. As shown in Figure
3, the mantissa sign (S) and exponent (E) should be placed im-
mediately after the mantissa.
[Figure 4 code example]
D4 0500 D->AC ;convert radius R to binary
D4 072C 01 AC->V1 ;store R in variable V1
D4 0754 08 EE 87 64 00 82 PI -> AC ; load AC with Pi
D4 0705 01 V1->OP ; load OP with V1=R
D4 02B7 AC*OP->AC ;ac = Pi*R
D4 02B7 AC*OP->AC ;ac = Pi*R*R
D4 0598 AC->D ;convert to decimal into D
The example shown in Figure 4 illustrates how some of
these routines may be used to find the area of a circle, given
its radius.
Figure 5 is a listing of the hex code for the ﬂoating point
arithmetic subroutine package. These subroutines start at
the beginning of memory page 01 and end at the last byte of
page 08. Page 08 is used for the variable storage. If you want
to change the location in memory of these subroutines you
must always start them at the beginning of a page. Also,
certain modiﬁcations to the routines must be made.
For example, if you want to move the beginning of the subroutine
package two pages, from page 01 to page 03 in memory,
you must add 02 to all of the underlined bytes. You would
also have to add 02 to the high order byte of all the routine
calling addresses. This subroutine package uses the follow-
ing 1802 registers: R(A), R(B), and R(C). In addition, the
square root routine uses register R(D) and variables 26 (hex)
and 27 (hex). Please note that the SCRT (which you must
supply) uses R(2), R(3), R(4) and R(5). [Herb: also R(6)
as a link to arguments after the calling address.]
Using this ﬂoating point arithmetic package, I have been
able to write routines that generate exponentials, sines and
cosines. I hope that you will fmd these routines as useful
as I have.