` COMPUTE! ISSUE 11 / APRIL 1981 / PAGE 66`

A Floating-Point Binary To BCD Routine

Marvin L. DeJong
Department of Mathematics-Physics
The School of the Ozarks
Pt. Lookout, MO 65726

Introduction

A previous issue of COMPUTE! carried a BCD to Floating-Point Binary Routine that can be used to convert a series of decimal digits and a decimal exponent to a binary number in a floating-point format. The purpose of such a routine is to enable the user to perform floatingŁpoint arithmetic. The program described in this article performs the reverse operation; that is, it converts a floating-point binary number to a decimal number and a decimal exponent. With these two routines and an Am9511 Arithmetic Processing Unit one can do most of the functions found on scientific calculators. I hope to proŁvide a few simple arithmetic routines in the near future. In the meanwhile, you can amuse yourself by converting numbers to floatingŁpoint binary numbers and then back to decimal numbers.

Hindsight

The BCD to floating-point binary routine described previously used a divide-by-ten routine that was part of the main program. With my excellent hindsight I now realize that the divide-by-ten routine should have been written as a subroutine, to be called by both the BCD to floating-point binary routine and the binary to decimal routine described here. So my first task was to rewrite the divide-by-ten routine as a subroutine. I also discovered that the divide-by-ten routine described in the previous article did not give sufficient precision. In any case, the divide-by-ten routine was completely revised and appears in Listing 1 in this article. It uses the location \$0000, called OVFLO, as a "guard" byte to give the necessary precision. It actually starts at \$0EC5, but our listing starts at \$0EBF to indiciate a few changes that must be made in the original listing to insert the subroutine.

 Listing 1. A New Divide-by-Ten Routine. \$OEBF 20 C5 0E ONCMOR JSR DIVTEN Jump to divide-by-ten subroutine. 0EC2 B8 CLV Force a jump around the routine. 0EC3 50 51 BVC ARND The new subroutine is inserted here. Clear accumulator for use as a register. Do \$28 = 40 bit divide. OVFLO will be used as "guard" byte. 0EC5 A9 00 DIVTEN LDA \$00 0EC7 A0 28 LDY \$28 0EC9 06 00 BRA ASL OVFLO 0ECB 26 04 ROL LSB 0ECD 26 03 ROL NLSB Roll one bit at a time into the accumulator which serves to hold the partial dividend. 0ECF 26 02 ROL NMSB 0ED1 26 01 ROL MSB 0ED3 2A ROL A Check to see if A is larger than the divisor, \$0A = 10. 0ED4 C9 0A CMP \$0A 0ED6 90 05 BCC BRB No. Decrease the bit counter. 0ED8 38 SEC Yes. Subtract divisor from A. 0ED9 E9 0A SBC \$0A 0EDB E6 00 INC OVFLO Set a bit in the quotient. 0EDD 88 BRB DEY Decrease the bit counter. 0EDE D0 E9 BNE BRA 0EE0 C6 05 BRC DEC BEXP Division is finished, now normalize. 0EE2 06 00 ASL OVFLO For each shift left, decrease the binary exponent. 0EE4 26 04 ROL LSB 0EE6 26 03 ROL NLSB Rotate the mantissa left until a one is in the most-significant bit. 0EE8 26 02 ROL NMSB 0EEA 26 01 ROL MSB 0EEC 10 F2 BPL BRC 0EEE A5 00 LDA OVFLO If the most-significant bit in the guard byte is one, round up. 0EF0 10 12 BPL BRE 0EF2 38 SEC Add one. 0EF3 A2 04 LDX \$04 X is byte counter. 0EF5 B5 00 BRD LDA ACC, X Get the LSB. 0EF7 69 00 ADC \$00 Add the carry. 0EF9 95 00 STA ACC, X Result into mantissa. 0EFB CA DEX 0EFC DO F7 BNE BRD Back to complete addition. 0EFE 90 04 BCC BRE No carry from MSB so finish. 0F00 66 01 ROR MSB A carry, put in bit seven, and increase the binary exponent. 0F02 E6 05 INC BEXP 0F04 A9 00 BRE LDA \$00 Clear the OVFLO position, then get out. 0F06 85 00 STA OVFLO 0F08 60 RTS . . . . Empty memory locations here. . . 0F16 A9 00 ARND LDA \$00 Remainder of BCD-to-floating . . : : point routine is here.
 Listing 2. Modifications to the BCD-to-Floating-Point Binary Routine. \$0E54 18 CLC Clear carry for addition. 0E55 A5 05 LDA BEXP Get binary exponent. 0E57 69 20 ADC \$20 Add \$20 = 32 to place binary 0E59 85 05 STA BEXP point properly. 0E5A EA NOP 0E5B EA NOP \$0D53 A0 20 BR7 LDY \$20 Y will limit the number of left shifts to 32. 0D55 A5 01 BR10 LDA MSB 0D57 30 0D BMI BR11 If mantissa has a one in its most-significant bit, get out. 0D59 18 CLC 0D5A A2 04 LDX \$04 0D5C 36 00 BR9 ROL ACC,X Shift accumulator left one bit. 0D5E CA DEX 0D5F D0 FB BNE BR9 0D61 C6 05 DEC BEXP Decrement binary exponent for each left shift. OD63 88 DEY 0D64 D0 EF BNE BR10 No more than \$20 = 32 bits shifted. 0D66 60 BR11 RTS That's it.

Some other minor modifications to the program are given in Listing 2. Although the BCD to Floating-Point Binary program will work without these changes, it will work better if you introduce the changes shown in Listing 2. The development of the program described in this article enabled me to find some places to improve the other routine. The modifications are simple and short.

The Conversion Routine

The program to convert a normalized floating-point binary number and its exponent to a BCD number and then output the result is given in Listing 3. A 32-bit binary to BCD conversion subroutine is called by this program and it is found in Listing 5. A flowchart of the entire process is given in Figure 1. The normalized floating-point binary mantissa is operated on by a series of "times ten" or "divide by ten" operations until the binary point is moved from the left of the mantissa to the right of the 32 bit mantissa. In other words, we multiply by ten or divide by ten until the binary exponent is 32. Then the mantissa represents an integer and can be converted to a BCD number using the subroutine in Listing 5. The algorithm for this latter routine is from Peatman's (John B)

Microprocessor Based Design

(McGraw-Hill).

Of course, each time the binary number is multiplied by ten or divided by ten the decimal exponent is adjusted. Thus, we are left with a BCD number in locations \$0020 - \$0024 (five locations for ten digits) and a decimal exponent in \$0017. The rest of the routine is largely processing required to give a reasonable output format. Since we don't want to print a group of non-significant zeros, the BCD number is rotated right until all the zeros are shifted out or the decimal exponent is zero, whichever comes first.

Next the routine starts examining the BCD number from the left and skips any leading zeros. Thus, the first non-zero digit is the first digit printed. Of course, if the number is minus (a non-zero result in location \$0007) a minus sign is printed. Next the decimal point is printed, and finally the exponent is printed in the form "E XX." Thus, the format chosen always has the decimal point to the right of the significant digits, 3148159. E-6 for example. If you want scientific notation for non-integer results you can modify the output routine. It's simply a matter of moving the decimal point. The flowchart and the comments should allow you to understand and modify the code. Figure 1. Flowchart of the Floating-Point Binary to BCS Routine.
 Listing 4. Subroutine OUTCH For the AIM 65. \$OFA6 20 00 F0 OUTCH JSR PRINT AIM 65 monitor subroutine. OFA9 20 72 0F JSR MODIFY See previous article in COMPUTE! 0FAC 20 60 0F JSR DISPLAY See previous article in COMPUTE! 0FAF 60 RTS RTS
 Listing 5. A 32 Bit Binary-to-BCD Subroutine. \$0D67 A2 05 CONVD LDX \$05 Clear BCD accumulator. 0D69 A9 00 LDA \$00 0D6B 95 20 BRM STA BCDA,X Zeros into BCD accumulator. 0D6D CA DEX 0D6E 10 FB BPL BRM 0D70 F8 SED Decimal mode for add. 0D71 A0 20 LDY \$20 Y has number of bits to be converted. Rotate binary number into carry. 0D73 06 04 BRN ASL LSB 0D75 26 03 ROL NLSB 0D77 26 02 ROL NMSB 0D79 26 01 ROL MSB D7B A2 FB LDX \$FB X will control a five byte addition. Get least-significant byte of the BCD accumulator, add is to itself, then store. 0D7D B5 25 BRO LDA BCDA,X 0D7F 75 25 ADC BCDA,X 0D81 95 25 STA BCDA,X 0D83 E8 INX Repeat until all five bytes have been added. 0D84 D0 F7 BNE BRO 0D86 88 DEY Get another bit from the binary number. 0D87 D0 EA BNE BRN 0D89 D8 CLD Back to binary mode. 0D8A 60 RTS And back to the program.