Written by: 0AFC PO ST PR 0EDF CLEAR PRB Read by: 0B1D PO F PR P READ 1AC8 see 1A7A syntax offset table precision Means, roughly, "the number of correct digits obtained as the result of a calculation". There are many ways of representing numbers in print, but most of them involve a string of digits, eg binary, hex or decimal. The first digit is most significant and the last, besides being least significant, is usually slightly inaccurate.Pi, for example, is somewhere between 3.1415 and 3.1416 decimal,closer to 3.1416, but no finite string of decimal digits can represent it exactly, nor of binary or hex digits; only integersand exact fractions can be written in digits without rounding, and_exact representations of "real numbers" like pi can only be given by infinite series. The 5-byte FP number form represents numbers with a maximum precision of 32d binary digits, which is equivalent to between nine and ten decimal digits, but the Spectrum only prints out numbers with eight decimal digits - the eighth is rounded to give as good a representation as possible of the missing digits. This is not a limitation of the computer: it is not very difficult to rewrite the calculator's main arithmetic routines in a m/c program so as to use eg a 6-byte or 8-byte mantissa, with precision of 48d or 64d binary digits, 14d plus and 19d plus decimal digits. 32d-digit precision is maintained in multiplication and division by giving the mantissa a temporary fifth byte, and using its hi bit, the_33rd_binary_digit, to round the 32nd digit. Even the_34th_binary_digit has some significance in additions. All rounding from calculations is binary rounding, whichis very simple: round up if the last digit is one, down if it iszero. This is sometimes referred to as_adding_in_the_carry _from_the_calculation. If the mileage indicator in your car only shows 5 figures, and you have done 99,999d miles, when you complete another mile_the_carry_will_ripple right back to the left-hand digit and your indicator will show 00000. This illustrates the use of the term in the notes, except that there it is always binary digits which are in question. 2DE3 PRINT FP rounds X to eight digits 2EB8 PF ALL 9 round up if ninth digit set 2EDF PF FRN LP round up 8-digit integer if fraction part 2F0C PF ROUND round print buffer to maximum 8 digits 2F18 PF RND LP add carry to round up or down 2F25 PF R BACK jump back to round again 2FDD SHIFT FP add back carry and set to zero if it ripples back 2FE5 ONE SHIFT check for ripple back of carry 3004 ADD BACK add back carry and check for ripple 316E SHIFT ONE mantissa has temporary fifth byte to ensure 32d-digit precision 3186 NORML NOW add back carry and check for ripple 31AF division 32 binary digit precision obtained 31FA COUNT ONE the 33rd binary digit is needed for precision in the 32nd P REM 1AA5 see 1A7A syntax offset table PR END Z subroutine 2045 See 1FCD PRINT. Called from: 1FDF PRINT 2 2067 PR POSN 3 PREP ADD subroutine 2F9B See 303E FULL ADDN; this subroutine is really part of FULL ADDN. Performs step 1. as explained in the introduction to FULL ADDN, and also: - negates the mantissa if it is a negative number - returns the exponent byte and a five-byte mantissa separately: the first byte of the mantissa is now a sign byte, 00 for a positive number, FF for a negative number. Thus pi, 82 49 0F DA A2, becomes 82 and 00 C9 0F DA A2, minus pi, 82 C9 0F DA A2, becomes 82 and FF 36 F0 25 5E. Input parameters: HL is the first address of the five bytes of the number, which must be in full format, not a small integer. Action: get the exponent - zero the first byte; this is now the sign byte - if the exponent was zero, return; the number must be zero - move the pointer on to the second byte; its hi bit is the sign marker, zero for positive and one for negative - check the sign marker and set it anyway; making the mantissa a true mantissa - if it was zero, return; the number is positive, and all necessary action has been taken - (negative number) make a counter of five for the bytesof the number - move the pointer past the last byte - set the carry flag. _2FAF_NEG_BYTE: decrement the pointer - get the byte at the pointer - CPL it and add in the carry; the CPL instruction doesn't affect the carry flag, so the last byte is subtracted from 100h, the others from FFh, unless the fifth byte was 00 to start with, in which case it is restored to 00 and the carry goes on to the next byte - loop back to NEG BYTE till all five bytes have been changed; the sign byte becomes FFh. Exit: RET, from PREP ADD for a positive or NEG BYTE for anegative number. Output parameters: A holds the exponent byte - others unchanged. Called from: 303E FULL ADDN (twice) PREP M/D subroutine 30C0 Called for each operand of a long multiplication or division, after the operands have been put in full FP format; makes the only adjustment required for multiplication or division, ie sets the hi bit of the mantissa. But it also figures the sign of the result, which will be positive for like signs of the two operands, negative if they are different. Input parameters: HL holds the first address of the FP number - A holds a sign flag, which is zero on the first call to PREP M/D. Action: call 34E9 TEST ZERO - if the number is zero return with carry - move the pointer on to the sign byte of the number - XOR the sign byte with the sign flag; only bit 7 is significant - it will be set if the signs are unlike, zeroed if they are alike - set the hi bit of the mantissa; this makes a "true mantissa". Exit: RET. Output parameters: all registers unchanged except A; after both sign bytes have been XORed with its starting zero, its hi bit will be one for unlike signs, zero for like, ie signalling the sign bit of the result - the carry flag is set if the number was zero. Called from: 30F0 MULT LONG (twice) 31AF division (twice) present character see 0018 GET CHAR P RESTORE 1ACF P RETURN 1A8D see 1A7A syntax parameter table PRINT key (F5) see also commands, functions and operators, KEYBOARD SCANNING The P key in K mode shift produces the command PRINT. The "PRINT statement" may, but need not, include position and colour controls and one or more operands, string or numeric expressions separated by position controllers. It may also include (hatch) with a stream number. It outputs the operands, or a newline if none are given, to the chosen stream, or to stream 2 channel S if none is specified. The command is read by 1B29 STMT L 1 referring through the syntax offset table 1A48 to the syntax parameter table 1A7A.1A9C P PRINT causes a jump via 1C11 CLASS 05 and 1C16 JUMP C R to the executive routine 1FCD PRINT. 0364 K TOKENS converts letter P to command PRINT PRINT subroutine 1FCD Called only from 1A9C P PRINT in the syntax parameter table; the executive routine for the PRINT command. It outputs its operands to channel S, main screen, unless another stream isspecified, using the permanent colours unless others are specified. All of the PRINT command routine is common to the LPRINTcommand, the only difference being in the stream number set at the start. Parts of it are also called as subroutines by the 2089 INPUT command routine, and one minor part by the 0605 SAVE ETC command routine. These subroutines are described here as part of this routine, for the sake of clarity. Input parameters: none. Action: make the stream number 2. _1FCF_PRINT_1: call 1601 CHAN OPEN to open the specified channel; stream 3 channel P, ZX printer, in the case of LPRINT, stream 2 channel S main screen in the case of PRINT - call 0D4D TEMPS to use the permanent colours [a redundant call: 1601 CHAN OPEN has just exited through TEMPS from 1646 CHAN S 1, for either of the screen outputs] - call PRINT 2; see immediately below - call 1BEE CHECK END, which in syntax checking reports an error if the end of the statement has not been reached and makes a double return to the statement loop if it has - (run time) return; to the statement loop. _1FDF_PRINT_2 (formally an independent subroutine, but the only call outside the PRINT command routine is from 2089 INPUT, to handle the INK to TAB controls): get the first code ofthe PRINT or INPUT statement - call PR END Z; see immediately below - if the code is newline, colon or 29h ) jump on to PRINT 4. _1FE5_PRINT_3 (the code is not a terminator): call PR POSN 1 to check for and execute the semicolon, comma and newlineposition controls; see immediately below - if it returns with zero loop back to PRINT 3; a position control was executed, so look for more - call PR ITEM 1 to check for and execute AT, TAB, and the colour controls or to output string or numeric expressions; see immediately below - call PR POSN 1 again, and again loop back to PRINT 3 if any position controls are executed. _1FF2_PRINT_4 (either a terminator has been encountered, or there are no more position controls): if the code is 29h ), return; this must be the close of an INPUT prompt. _1FF5_PRINT_CR (also called as a subroutine by PR POSN 2): output a newline and return; the end of the PRINT statement has been reached. This is bypassed if the PRINT statement ends with a position control, eg semicolon, see PR POSN 3 below. _1FFC_PR_ITEM_1 (another formally independent subroutine,but outside the PRINT routine called only by 21AF IN NEXT 1 in the INPUT command routine): read the first code - if it's not "AT" jump on to PR ITEM 2 - ("AT") call 1C79 NEXT 2NUM and 2307 STK TO BC to collect the two parameters - jump on to PR AT TAB with them and the AT control code16h. _200E_PR_ITEM_2: if the code isn't TAB jump to PR ITEM 3 - ("TAB") call 1C82 EXPT 1NUM and 1E99 FIND INT2 to readthe parameter from BASIC into BC; there is only one parameter, but it may be a 2-byte number - enter PR AT TAB with the TAB control code 17h. _201E_PR_AT_TAB: call the output routine 0010 PRINT A 1 three times, once with the control code and once with each parameter; this triple call is used to execute indirect jumps within the 0A75 PO 2 OPER routine, so as to handle the control code and its operands together. See under 09F4 PRINT OUT - return, into PRINT 3. _2024_PR_ITEM_3 (not AT or TAB): call 21F2 CO TEMP 3, which checks for and executes any colour controls - if it returns with no carry, return, into PRINT 3; a colour control was executed - call 2070 STR ALTER to check for and execute any instructions such as "PRINT (hatch) 0" - if it returns with no carry, return, into PRINT 3; thestream has been altered - (the next code isn't a position controller, a colour control, an AT or TAB, or a hatch, so it must be interpreted as an expression to be output) call 24FB SCANNING, which puts its numeric value or its string parameters on the calculator stack - if bit 6 of FLAGS is zero call 2BF1 STK FETCH, to get the start pointer and length from the stack; it doesn't affect the Z flag. Bit 6 is the string/numeric flag, zero for a string,one for a numeric result - if it is one exit into 2DE3 PRINT FP; the complicated routine to print a numeric result which is described separately in this index. Its return will be into PRINT 3. _203C_PR_STRING (output a string): check the length - decrement it - if it was zero return, to PRINT 3; either it was a null string, or the loop has now output all its bytes - read the byte at the pointer and move the pointer on - call 0010 PRINT A 1 to output the byte - loop back to PR STRING. _2045_PR_END_Z (again formally a subroutine, but called only from PRINT 2 and PR POSN 3): if the code is 29h ), return; this must be the end of an INPUT prompt. _2048_PR_ST_END (another formal subroutine, this one called also from 06C3 SA CODE to check if the statement ends after SAVE/LOAD ... CODE): if the code is a newline or a colon, return. _204E_PR_POSN_1 (yet another formal subroutine, called from 20C1 IN ITEM 1 and 21B2 IN NEXT 2 in the INPUT command routine apart from the two calls in PRINT 3): get the code - if it is 3B semicolon jump on to PR POSN 3; the semicolon is a position controller, but no action is taken on it - if it isn't 2C comma jump on to PR POSN 2 - (it is a comma) output a PRINT comma, code 06 - jump on to PR POSN 3. _2061_PR_POSN_2 (not semicolon or comma): if it isn't 27hsingle quote, return with NZ to PRINT 3; not a position controller - (it is a quote, calling for a newline) call 1FF5 PRINTCR (misprinted) to execute the newline. _2067_PR_POSN_3 (a position controller has been executed): get the next character - call PR END Z - if it returns with NZ jump on to PR POSN 4; not the end of the PRINT statement - (end of PRINT statement) drop a return address, makinga double return to the statement loop; bypassing the final newline if the PRINT statement ends with a position controller _206E_PR_POSN_4: set the Z flag [ie make it Z; "reset" inthe notes is a misprint] - return. Exit: the RETs in PRINT 1, PRINT 4 and PRINT CR, except of course when it is a subroutine called from PR POSN 2, all go back to 1B76 STMT RET - the RETs in PR AT TAB, PR ITEM 3, PR END Z, PR ST END,PR POSN 2 and PR POSN 4 are all "internal" returns, staying within the command routine, except when the return address is dropped in PR POSN 4 causing a return to STMT RET. - PR ITEM 3 exits to 2DE3 PRINT FP to output a number, but the return from there will again be into PRINT 3. Output parameters: none. printable characters see character codes, 0B24 PO ABLE PRINT A CARRIAGE RETURN SUBROUTINE see 1EF5 PRINT CR under 1FCD PRINT PRINT A CHARACTER RESTART see 0010 PRINT A 1 print address used to mean "pixel address in the display area" in 0B6A PO CHAR 2; see DISPLAY AREA PRINT A FLASHING CHARACTER SUBROUTINE see 1BC1 OUT FLASH