Routines 
Prev: 11733  Up: Map  Next: 12171 
This subroutine prints x, the 'last value' on the calculator stack. The print format never occupies more than 14 spaces.
The 8 most significant digits of x, correctly rounded, are stored in an ad hoc print buffer in mem3 and mem4. Small numbers, numerically less than 1, and large numbers, numerically greater than 2↑27, are dealt with separately. The former are multiplied by 10↑n, where n is the approximate number of leading zeros after the decimal, while the latter are divided by 10↑(n7), where n is the approximate number of digits before the decimal. This brings all numbers into the middle range, and the number of digits required before the decimal is built up in the second byte of mem5. Finally the printing is done, using Eformat if there are more than 8 digits before the decimal or, for small numbers, more than 4 leading zeros after the decimal.
The following program shows the range of print formats:
10 FOR a=11 TO 12: PRINT SGN a*9↑a,: NEXT a
i. First the sign of x is taken care of:


PRINT_FP  11747  RST 40  Use the calculator.  
11748  DEFB 49  duplicate: x, x  
11749  DEFB 54  less_0: x, (1/0) Logical value of x.  
11750  DEFB 0,11  jump_true to PF_NEGTVE: x  
11752  DEFB 49  duplicate: x, x  
11753  DEFB 55  greater_0: x, (1/0) Logical value of x.  
11754  DEFB 0,13  jump_true to PF_POSTVE: x Hereafter x'=ABS x.  
11756  DEFB 2  delete:   
11757  DEFB 56  end_calc:   
11758  LD A,"0"  Enter the character code for '0'.  
11760  RST 16  Print the '0'.  
11761  RET  Finished as the 'last value' is zero.  
PF_NEGTVE  11762  DEFB 42  abs: x' x'=ABS x.  
11763  DEFB 56  end_calc: x'  
11764  LD A,""  Enter the character code for ''.  
11766  RST 16  Print the ''.  
11767  RST 40  Use the calculator again.  
PF_POSTVE  11768  DEFB 160  stk_zero: The 15 bytes of mem3, mem4 and mem5 are now initialised to zero to be used for a print buffer and two counters.  
11769  DEFB 195,196,197  
11772  DEFB 2  delete: The stack is cleared, except for x'.  
11773  DEFB 56  end_calc: x'  
11774  EXX  HL', which is used to hold calculator offsets (e.g. for 'STR$'), is saved on the machine stack.  
11775  PUSH HL  
11776  EXX  
ii. This is the start of a loop which deals with large numbers. Every number x is first split into its integer part i and the fractional part f. If i is a small integer, i.e. if 65535<=i<=65535, it is stored in DE' for insertion into the print buffer.


PF_LOOP  11777  RST 40  Use the calculator again.  
11778  DEFB 49  duplicate: x', x'  
11779  DEFB 39  int: x', INT (x')=i  
11780  DEFB 194  st_mem_2: (i is stored in mem2).  
11781  DEFB 3  subtract: x'i=f  
11782  DEFB 226  get_mem_2: f, i  
11783  DEFB 1  exchange: i, f  
11784  DEFB 194  st_mem_2: (f is stored in mem2).  
11785  DEFB 2  delete: i  
11786  DEFB 56  end_calc: i  
11787  LD A,(HL)  Is i a small integer (first byte zero) i.e. is ABS i<=65535?  
11788  AND A  
11789  JR NZ,PF_LARGE  Jump if it is not.  
11791  CALL INT_FETCH  i is copied to DE (i, like x', >=0).  
11794  LD B,16  B is set to count 16 bits.  
11796  LD A,D  D is copied to A for testing: is it zero?  
11797  AND A  
11798  JR NZ,PF_SAVE  Jump if it is not zero.  
11800  OR E  Now test E.  
11801  JR Z,PF_SMALL  Jump if DE is zero: x is a pure fraction.  
11803  LD D,E  Move E to D and set B for 8 bits: D was zero and E was not.  
11804  LD B,8  
PF_SAVE  11806  PUSH DE  Transfer DE to DE', via the machine stack, to be moved into the print buffer at PF_BITS.  
11807  EXX  
11808  POP DE  
11809  EXX  
11810  JR PF_BITS  Jump forward.  
iii. Pure fractions are multiplied by 10↑n, where n is the approximate number of leading zeros after the decimal; and n is added to the second byte of mem5, which holds the number of digits needed before the decimal; a negative number here indicates leading zeros after the decimal.


PF_SMALL  11812  RST 40  i (i=zero here)  
11813  DEFB 226  get_mem_2: i, f  
11814  DEFB 56  end_calc: i, f  
Note that the stack is now unbalanced. An extra byte 'DEFB 2, delete' is needed immediately after the RST 40. Now an expression like "2"+STR$ 0.5 is evaluated incorrectly as 0.5; the zero left on the stack displaces the "2" and is treated as a null string. Similarly all the string comparisons can yield incorrect values if the second string takes the form STR$ x where x is numerically less than 1; e.g. the expression "50"<STR$ 0.1 yields the logical value "true"; once again "" is used instead of "50".


11815  LD A,(HL)  The exponent byte e of f is copied to A.  
11816  SUB 126  A becomes e minus 126, i.e. e'+2, where e' is the true exponent of f.  
11818  CALL LOG_2_A  The construction A=ABS INT (LOG (2↑A)) is performed (LOG is to base 10); i.e. A=n, say: n is copied from A to D.  
11821  LD D,A  
11822  LD A,(23724)  The current count is collected from the second byte of mem5 and n is subtracted from it.  
11825  SUB D  
11826  LD (23724),A  
11829  LD A,D  n is copied from D to A.  
11830  CALL e_to_fp  y=f*10↑n is formed and stacked.  
11833  RST 40  i, y  
11834  DEFB 49  duplicate: i, y, y  
11835  DEFB 39  int: i, y, INT (y)=i2  
11836  DEFB 193  st_mem_1: (i2 is copied to mem1).  
11837  DEFB 3  subtract: i, yi2  
11838  DEFB 225  get_mem_1: i, yi2, i2  
11839  DEFB 56  end_calc: i, f2, i2 (f2=yi2)  
11840  CALL FP_TO_A  i2 is transferred from the stack to A.  
11843  PUSH HL  The pointer to f2 is saved.  
11844  LD (23713),A  i2 is stored in the first byte of mem3: a digit for printing.  
11847  DEC A  i2 will not count as a digit for printing if it is zero; A is manipulated so that zero will produce zero but a nonzero digit will produce 1.  
11848  RLA  
11849  SBC A,A  
11850  INC A  
11851  LD HL,23723  The zero or one is inserted into the first byte of mem5 (the number of digits for printing) and added to the second byte of mem5 (the number of digits before the decimal).  
11854  LD (HL),A  
11855  INC HL  
11856  ADD A,(HL)  
11857  LD (HL),A  
11858  POP HL  The pointer to f2 is restored.  
11859  JP PF_FRACTN  Jump to store f2 in buffer (HL now points to f2, DE to i2).  
iv. Numbers greater than 2↑27 are similarly multiplied by 2↑(n+7), reducing the number of digits before the decimal to 8, and the loop is reentered at PF_LOOP.


PF_LARGE  11862  SUB 128  e minus 128 is e', the true exponent of i.  
11864  CP 28  Is e' less than 28?  
11866  JR C,PF_MEDIUM  Jump if it is less.  
11868  CALL LOG_2_A  n is formed in A.  
11871  SUB 7  And reduced to n7.  
11873  LD B,A  Then copied to B.  
11874  LD HL,23724  n7 is added in to the second byte of mem5, the number of digits required before the decimal in x.  
11877  ADD A,(HL)  
11878  LD (HL),A  
11879  LD A,B  Then i is multiplied by 10↑(n+7). This will bring it into medium range for printing.  
11880  NEG  
11882  CALL e_to_fp  
11885  JR PF_LOOP  Round the loop again to deal with the now mediumsized number.  
v. The integer part of x is now stored in the print buffer in mem3 and mem4.


PF_MEDIUM  11887  EX DE,HL  DE now points to i, HL to f.  
11888  CALL FETCH_TWO  The mantissa of i is now in D', E', D, E.  
11891  EXX  Get the exchange registers.  
11892  SET 7,D  True numerical bit 7 to D'.  
11894  LD A,L  Exponent byte e of i to A.  
11895  EXX  Back to the main registers.  
11896  SUB 128  True exponent e'=e minus 128 to A.  
11898  LD B,A  This gives the required bit count.  
Note that the case where i is a small integer (less than 65536) reenters here.


PF_BITS  11899  SLA E  The mantissa of i is now rotated left and all the bits of i are thus shifted into mem4 and each byte of mem4 is decimal adjusted at each shift.  
11901  RL D  
11903  EXX  
11904  RL E  
11906  RL D  
11908  EXX  Back to the main registers.  
11909  LD HL,23722  Address of fifth byte of mem4 to HL; count of 5 bytes to C.  
11912  LD C,5  
PF_BYTES  11914  LD A,(HL)  Get the byte of mem4.  
11915  ADC A,A  Shift it left, taking in the new bit.  
11916  DAA  Decimal adjust the byte.  
11917  LD (HL),A  Restore it to mem4.  
11918  DEC HL  Point to next byte of mem4.  
11919  DEC C  Decrease the byte count by one.  
11920  JR NZ,PF_BYTES  Jump for each byte of mem4.  
11922  DJNZ PF_BITS  Jump for each bit of INT (x).  
Decimal adjusting each byte of mem4 gave 2 decimal digits per byte, there being at most 9 digits. The digits will now be repacked, one to a byte, in mem3 and mem4, using the instruction 'RLD'.


11924  XOR A  A is cleared to receive the digits.  
11925  LD HL,23718  Source address: first byte of mem4.  
11928  LD DE,23713  Destination: first byte of mem3.  
11931  LD B,9  There are at most 9 digits.  
11933  RLD  The left nibble of mem4 is discarded.  
11935  LD C,255  255 in C will signal a leading zero, 0 will signal a nonleading zero.  
PF_DIGITS  11937  RLD  Left nibble of (HL) to A, right nibble of (HL) to left.  
11939  JR NZ,PF_INSERT  Jump if digit in A is not zero.  
11941  DEC C  Test for a leading zero: it will now give zero reset.  
11942  INC C  
11943  JR NZ,PF_TEST_2  Jump if it was a leading zero.  
PF_INSERT  11945  LD (DE),A  Insert the digit now.  
11946  INC DE  Point to next destination.  
11947  INC (IY+113)  One more digit for printing, and one more before the decimal.  
11950  INC (IY+114)  
11953  LD C,0  Change the flag from leading zero to other zero.  
PF_TEST_2  11955  BIT 0,B  The source pointer needs to be incremented on every second passage through the loop, when B is odd.  
11957  JR Z,PF_ALL_9  
11959  INC HL  
PF_ALL_9  11960  DJNZ PF_DIGITS  Jump back for all 9 digits.  
11962  LD A,(23723)  Get counter from the first byte of mem5: were there 9 digits excluding leading zeros?  
11965  SUB 9  
11967  JR C,PF_MORE  If not, jump to get more digits.  
11969  DEC (IY+113)  Prepare to round: reduce count to 8.  
11972  LD A,4  Compare 9th digit, byte 4 of mem4, with 4 to set carry for rounding up.  
11974  CP (IY+111)  
11977  JR PF_ROUND  Jump forward to round up.  
PF_MORE  11979  RST 40  Use the calculator again.  
11980  DEFB 2  delete:  (i is now deleted).  
11981  DEFB 226  get_mem_2: f  
11982  DEFB 56  end_calc: f  
vi. The fractional part of x is now stored in the print buffer.


PF_FRACTN  11983  EX DE,HL  DE now points to f.  
11984  CALL FETCH_TWO  The mantissa of f is now in D', E', D, E.  
11987  EXX  Get the exchange registers.  
11988  LD A,128  The exponent of f is reduced to zero, by shifting the bits of f 128 minus e places right, where L' contained e.  
11990  SUB L  
11991  LD L,0  
11993  SET 7,D  True numerical bit to bit 7 of D'.  
11995  EXX  Restore the main registers.  
11996  CALL SHIFT_FP  Now make the shift.  
PF_FRN_LP  11999  LD A,(IY+113)  Get the digit count.  
12002  CP 8  Are there already 8 digits?  
12004  JR C,PF_FR_DGT  If not, jump forward.  
12006  EXX  If 8 digits, just use f to round i up, rotating D' left to set the carry.  
12007  RL D  
12009  EXX  Restore main registers and jump forward to round up.  
12010  JR PF_ROUND  
PF_FR_DGT  12012  LD BC,512  Initial zero to C, count of 2 to B.  
PF_FR_EXX  12015  LD A,E  D'E'DE is multiplied by 10 in 2 stages, first DE then DE', each byte by byte in 2 steps, and the integer part of the result is obtained in C to be passed into the print buffer.  
12016  CALL CA_10A_C  
12019  LD E,A  
12020  LD A,D  
12021  CALL CA_10A_C  
12024  LD D,A  
12025  PUSH BC  The count and the result alternate between BC and BC'.  
12026  EXX  
12027  POP BC  
12028  DJNZ PF_FR_EXX  Loop back once through the exchange registers.  
12030  LD HL,23713  The start  1st byte of mem3.  
12033  LD A,C  Result to A for storing.  
12034  LD C,(IY+113)  Count of digits so far in number to C.  
12037  ADD HL,BC  Address the first empty byte.  
12038  LD (HL),A  Store the next digit.  
12039  INC (IY+113)  Step up the count of digits.  
12042  JR PF_FRN_LP  Loop back until there are 8 digits.  
vii. The digits stored in the print buffer are rounded to a maximum of 8 digits for printing.


PF_ROUND  12044  PUSH AF  Save the carry flag for the rounding.  
12045  LD HL,23713  Base address of number: mem3, byte 1.  
12048  LD C,(IY+113)  Offset (number of digits in number) to BC.  
12051  LD B,0  
12053  ADD HL,BC  Address the last byte of the number.  
12054  LD B,C  Copy C to B as the counter.  
12055  POP AF  Restore the carry flag.  
PF_RND_LP  12056  DEC HL  This is the last byte of the number.  
12057  LD A,(HL)  Get the byte into A.  
12058  ADC A,0  Add in the carry i.e. round up.  
12060  LD (HL),A  Store the rounded byte in the buffer.  
12061  AND A  If the byte is 0 or 10, B will be decremented and the final zero (or the 10) will not be counted for printing.  
12062  JR Z,PF_R_BACK  
12064  CP 10  
12066  CCF  Reset the carry for a valid digit.  
12067  JR NC,PF_COUNT  Jump if carry reset.  
PF_R_BACK  12069  DJNZ PF_RND_LP  Jump back for more rounding or more final zeros.  
12071  LD (HL),1  There is overflow to the left; an extra 1 is needed here.  
12073  INC B  
12074  INC (IY+114)  It is also an extra digit before the decimal.  
PF_COUNT  12077  LD (IY+113),B  B now sets the count of the digits to be printed (final zeros will not be printed).  
12080  RST 40  f is to be deleted.  
12081  DEFB 2  delete:   
12082  DEFB 56  end_calc:   
12083  EXX  The calculator offset saved on the stack is restored to HL'.  
12084  POP HL  
12085  EXX  
viii. The number can now be printed. First C will be set to hold the number of digits to be printed, not counting final zeros, while B will hold the number of digits required before the decimal.


12086  LD BC,(23723)  The counters are set (first two bytes of mem5).  
12090  LD HL,23713  The start of the digits (first byte of mem3).  
12093  LD A,B  If more than 9, or fewer than minus 4, digits are required before the decimal, then Eformat will be needed.  
12094  CP 9  
12096  JR C,PF_NOT_E  
12098  CP 252  Fewer than 4 means more than 4 leading zeros after the decimal.  
12100  JR C,PF_E_FRMT  
PF_NOT_E  12102  AND A  Are there no digits before the decimal? If so, print an initial zero.  
12103  CALL Z,OUT_CODE  
The next entry point is also used to print the digits needed for Eformat printing.


PF_E_SBRN  12106  XOR A  Start by setting A to zero.  
12107  SUB B  Subtract B: minus will mean there are digits before the decimal; jump forward to print them.  
12108  JP M,PF_OUT_LP  
12111  LD B,A  A is now required as a counter.  
12112  JR PF_DC_OUT  Jump forward to print the decimal part.  
PF_OUT_LP  12114  LD A,C  Copy the number of digits to be printed to A. If A is 0, there are still final zeros to print (B is nonzero), so jump.  
12115  AND A  
12116  JR Z,PF_OUT_DT  
12118  LD A,(HL)  Get a digit from the print buffer.  
12119  INC HL  Point to the next digit.  
12120  DEC C  Decrease the count by one.  
PF_OUT_DT  12121  CALL OUT_CODE  Print the appropriate digit.  
12124  DJNZ PF_OUT_LP  Loop back until B is zero.  
PF_DC_OUT  12126  LD A,C  It is time to print the decimal, unless C is now zero; in that case, return  finished.  
12127  AND A  
12128  RET Z  
12129  INC B  Add 1 to B  include the decimal.  
12130  LD A,"."  Put the code for '.' into A.  
PF_DEC_0S  12132  RST 16  Print the '.'.  
12133  LD A,"0"  Enter the character code for '0'.  
12135  DJNZ PF_DEC_0S  Loop back to print all needed zeros.  
12137  LD B,C  Set the count for all remaining digits.  
12138  JR PF_OUT_LP  Jump back to print them.  
PF_E_FRMT  12140  LD D,B  The count of digits is copied to D.  
12141  DEC D  It is decremented to give the exponent.  
12142  LD B,1  One digit is required before the decimal in Eformat.  
12144  CALL PF_E_SBRN  All the part of the number before the 'E' is now printed.  
12147  LD A,"E"  Enter the character code for 'E'.  
12149  RST 16  Print the 'E'.  
12150  LD C,D  Exponent to C now for printing.  
12151  LD A,C  And to A for testing.  
12152  AND A  Its sign is tested.  
12153  JP P,PF_E_POS  Jump if it is positive.  
12156  NEG  Otherwise, negate it in A.  
12158  LD C,A  Then copy it back to C for printing.  
12159  LD A,""  Enter the character code for ''.  
12161  JR PF_E_SIGN  Jump to print the sign.  
PF_E_POS  12163  LD A,"+"  Enter the character code for '+'.  
PF_E_SIGN  12165  RST 16  Now print the sign: '+' or ''.  
12166  LD B,0  BC holds the exponent for printing.  
12168  JP OUT_NUM_1  Jump back to print it and finish. 
Prev: 11733  Up: Map  Next: 12171 