- (VALUE has already passed LIMIT; BASIC execution must jump forward to the statement after the first matching NEXT) getthe variable letter from 5C72 STRLEN; it was parked there by 1C46 VAR A 3 when the call to 1C6C CLASS 04 was made from 1A90 PFOR. This is the letter as it appears in the program area, a simple letter code without discriminator bytes - put the_current line number from 5C45 PPC in 5C42 NEWPPC; the FOR and NEXT statements may both be in the same BASIC line - negate the current statement number from 5C47 SUBPPC; 198B EACH STMT called from LOOK PROG below counts statement numbers down to zero, so it requires a negative value to start with the one after the FOR - get the BASIC pointer from 5C5D CH ADD; it is on the terminator after the FOR statement - make a check byte F3 NEXT. _1D64_F_LOOP: get an end-of-line pointer from 5C55 NXTLIN; it is on the start of the next line in the program area - call 1D86 LOOK PROG to find the next F3 NEXT in the program - save the updated end-of-line pointer in 5C55 NXTLIN - if the carry flag is set report "FOR without NEXT"; nomore NEXTs is the program at all - (5C5D CH ADD is on a NEXT) move it on to the variable letter - OR the letter with 00100000b/20h to make it lower-case - if the result matches the current letter jump on to F FOUND - (wrong NEXT) move the BASIC pointer on again and jump back to F LOOP. _1D7C_F_FOUND: move the BASIC pointer on to the statementterminator after the NEXT statement - reverse the negation of the statement number made to suit EACH STMT - put the statement number in 5C44 NSPPC; 5C42 NEWPPC has already been filled by LOOK PROG. Exit: RET, from F L&S if a pass is required, from F FOUNDif not. In either case RET is to 1B76 STMT RET. Output parameters: none - the parameters are in the looping variable - if no pass is required, the line and statement numbersfollowing the NEXT statement are in 5C42 NEWPPC and 5C44 NSPPC - the calculator memory is still located in the variable; this will be corrected on return to the statement loopby the call to 16BF SET WORK in 1B29 STMT L 1. FORMAT key (D0) see also commands, functions and operators, KEYBOARD SCANNING, extended mode table 0284 The zero key in E mode with symbol shift produces the command FORMAT. The "FORMAT statement" isn't executed by the plain Spectrum, without attachments of some kind; with peripherals such as Interface 1 it requires to be followed by atleast a channel letter. The command is read by 1B29 STMT L 1 referring through the syntax offset table 1A48 to the syntax parameter table 1A7A.1B06 P FORMAT causes a jump via 1C8C CLASS 0A - which collects the letter - 1C10 CLASS OO and 1C16 JUMP C R to the executive routine 1793 CAT ETC - which however merely produces the error report "Invalid stream". FORM EXP 33DE (33C6 STK DATA) Jumps from: 33C8 STK CONST forms of numbers (integer and FP) see CALCULATE FOR ... NEXT control variables see FOR ... NEXT loops, variables FOR ... NEXT loops The terms used, eg in "FOR f = x TO y STEP z", are: _Loop_control_variable or_looping_variable is f _VALUE is x _LIMIT is y _STEP is z; if not specified, STEP is one. The_looping_line_and_statement specify the next statement after the FOR statement, read by the NEXT statement totell where to jump back. If the FOR statement is the last on itsline, this will address a non-existent statement, but the NEXT routine can take care of this. A_pass is one turn of the loop, up to "NEXT f". The VALUE, LIMIT and STEP, and looping line and statement, are all stored in eighteen bytes following the letterof the looping variable in the variables area; VALUE, LIMIT and STEP are in 5-byte FP format converted from the BASIC input, which can be any kind of numeric expression - decimal, BIN or E-format numbers, variables, functional expressions - and can be negative or fractional numbers; they aren't rounded to integers. If the VALUE variable is given a new value within the loop the looping takes account of the change, eg FOR f = 1 TO 1: LET f = f - 1: NEXT f will loop for ever. Changing the values of LIMIT and STEP in similar ways doesn't have similar effects: the values of the variables or expressions are changed for other purposes, but thelooping continues to use the old values. 1DAB NEXT adds STEP to VALUE and checks with LIMIT 1DDA NEXT LOOP checks LIMIT, with due regard to sign of STEP 1DE2 NEXT 1 return with NC if loop possible 1DE9 NEXT 2 return with C if loop not possible 2900 V EACH checks vble letter flags for loop vble fourteen pointers see 1664 POINTERS FP throughout this index = "floating point"; see CALCULATE FP A END 2DE1 (2DD5 FP TO A) Exit from: 2DD5 FP TO A FP CALC subroutine 0028 The_use of the floating point calculator is fully discussed under CALCULATE. There you will find explained: - the structure of FP numbers - full format/small integers/stk-data format - calculator literals - the calculator stack, last value, first and second operands, etc - the calculator memory. Also all significant Rems relating to FP CALC are listedthere. This entry confines itself to the actual operation of thesubroutine. A call to RST 28 must be followed by at least one _literal, a single byte which signals the calculation to be performed. If there is more than one, the calculations are performed in sequence, each one leaving its result on the calculator stack, and operating on the values it finds there from the preceding calculation. The last literal must be 38h/ 56d, signalling "end-calc", to exit from the subroutine. Subroutines which can be called by literals following FPCALC are shown in this index with their names in lower case; thefirst reference in each case is to the appropriate literal for FP CALC. For a complete list, see the table in the notes, or theROM listing, at 32D7. The notes make various distinctions between types of literals and operations, which can be expanded a little: _simple_literals call for a specific operation, eg "add" _unary_operations are those which have only one operand, eg "negate" _binary_operations have two operands, eg "add", "exchange"; sometimes the result is a single number, sometimes not _manipulatory_operations move numbers without changing them, eg "get-mem", "exchange" _comparison_operations are the twelve literals 09 no-l-eqlto 0E nos-eql and 11 str-l-eql to 16 strs-eql, see index entry 353B no-l-eql; a useful classification, but only obliquely used in the notes. These are all simple binary operations _multi-purpose_literals are those of which the hi digit specifies a group of operations and the lo digit specifies further, eg E0 to E5 specify "get-mem-0" to "get-mem-5" _programming_literals don't affect the values on the stackor in memory, but affect the calculation, eg "jump-true", "dec- jr-nz"; this type isn't mentioned in the classification in the notes, but it obviously needs a name. The binary operations are literals 00 to 17h; if the operation literal is less than 18h, HL and DE are moved back five places so that HL points to the_second last number on the calculator stack and DE to the last, instead of HL pointing to the last and DE to the end of the stack from 5C65 STKEND which is where they were placed when the calculator was entered. In two cases this moving of the pointers is the only point of the unary/binary distinction; the operators jump-true and delete areincluded as binary merely to get the pointers moved. The multi-purpose literals all have their hi bit set: 81h series-01 -> 9Fh series-1F: only series-06, series-08and series-0C are used in the ROM, but the others are available A0h stk-zero -> A4h stk-ten C0h st-mem-0 -> DFh st-mem-1F: only up to st-mem-5 are used in the ROM, but if memory is relocated the others are available E0h get-mem-0 -> FFh get-mem-1F: as for st-mem. All these are handled in SCAN ENT. The literal is ANDed with 60h, shifted right four times, and added to 7C, leaving 7C (twice 3E) for series 7E (twice 3F) for stk-const 80 (twice 40) for st-mem 82 (twice 41) for get-mem ie twice the value of the literal in the table at 3353 and following; this value is used to compute a jump to the required subroutine from ENT TABLE. Before the jump is made, the value ofthe last 5 bits is put in the A register, and later used to operate the required variant of the multi-purpose subroutine. If only one operation is to be performed, the literal 3Bcalling 33A2 fp-calc-2 may be used, with the B register holding the actual operation literal. This allows a series of operationsto be assembled on the machine stack and called in sequence, as from 274C S STK LIST. Input parameters: for many operations one or two values are needed on the calculator stack - the B register can hold either an operation literal ora loop counter; this will be kept, switching between the B register and 5C67 BREG, till either a literal 3B fp-calc-2 is encountered, when it will be executed as an operation literal or a literal 35 dec-jr-nz is encountered, when it willbe used as the loop counter. Action: jump straight on to CALCULATE. _335B_CALCULATE: call 35BF STK PNTRS which puts HL pointing to the first byte of the last value on the calculator stack and DE pointing to the stack end. _335E_GEN_ENT_1 [the entry point for the first call from 3449 series-06. The notes don't succeed in explaining why the more economical call to RST 28h wasn't used in this case. The only possible reason is to avoid resetting HL and DE by STK PNTRS; in fact every ROM call of series-06 immediately follows acall of 300F subtract, which leaves HL and DE with the identicalsettings. The call to STK PNTRS is unnecessary, but so far as ROM is concerned there is no reason to avoid it. Of course, one might construct a m/c program in which this is desirable]: put the value of B in 5C67 BREG. _3362_GEN_ENT_2 (the entry point for the looping calls from 3449 series-06; this time for the clear reason that the 35 dec-jr-nz literal is being used, which uses 5C67 BREG for a counter): put the "return address" of the subroutine in HL'; thebyte at this address is the next literal to be executed. _3365_RE_ENTRY (there is no direct call of or jump to RE ENTRY in ROM, but its address is put on top of the machine stackin 338E ENT TABLE, so all the subroutines called by literals return to here, except of course 38 end-calc): load 5C65 STKEND with DE - get the next literal from HL' - move HL' on one to point to the next "return address". _336C_SCAN_ENT (using the alternate registers; the entry point from 33A2 fp-calc-2): if the literal is less than 80h jumpon to FIRST 3D; these are all the simple operations 00 jump-true-> 3D re-stack - (multi-purpose literals 86 series-06 -> E5 get-mem-5) save the literal - AND it with 01100000b/60h; 8xh -> Fxh become 0xh -> 6xh - shift four times right; now they become 00 -> 06 - add the result to 7C for the jump offset; 7C (twice 3E) for series-0x -> 82 (twice 41) for get-mem-x - AND the saved literal with 00011111h/1Fh to get the parameter in the A register; it serves different purposes in thedifferent multi-purpose subroutines - jump on to ENT TABLE. _3380_FIRST_3D (simple literals): if the literal is more than 17h jump on to DOUBLE A; unary operations - (binary operations) return from the alternate registers - copy HL to DE and add FFFB/minus 05 to HL; this moves both back five places - go back into the alternate registers. _338C_DOUBLE_A (using the alternate registers; all literals have now been made less than 80h/128d): shift the literal one bit left; this doubles it and so makes an offset to compute the jump to the 2-byte subroutine address in the table. _338E_ENT_TABLE (using the alternate registers): make a base address 32D7 for the table - add the offset and read the subroutine address - get the address of the next literal into H'L and put the address 3365 RE ENTRY on the stack; all the calculator subroutines will return to RE ENTRY - put the computed subroutine address on the stack over RE ENTRY - return from the alternate registers - get the value of 5C67 BREG in the B register in case it is needed for the comparison operations; BREG is two above 5C65 STKEND, so LD BC,(STKENDhi), which would be better written LD BC,(BREG + 1), gets BREG in B. Exit: RET at 33A1; since the subroutine address has just been put on the stack, this RET is an indirect jump to the subroutine. The RET is labelled "delete", because this single RET is in fact also the delete subroutine; see index entry. In the case of delete the RET operates twice in succession. Output parameters: HL and DE point either to the last twovalues on the stack or to the last and the stack end address in 5C65 STKEND - B holds the value of 5C67 BREG; either a loop counter or the literal of the operation to be performed by fp-calc-2 - HL' holds the "return address" from FP CALC; it usually holds the next literal - the calculator stack and the calculator memory aren't disturbed, so repeated use of RST 28 FP CALC may be made with the same stack and memory. Called from: 03F8 BEEP 0427 BE OCTAVE (3 times) 1736 OPEN 1CE6 USE ZERO 1CF0 IF 1D10 F USE 1 1D16 F REORDER 1D34 F L&S 1DAB NEXT 1DDA NEXT LOOP 2320 CIRCLE (twice) 233B C R GRE 1 (4 times) 235A C ARC GE1 238D DR 3 PRMS 23A3 DR SIN NZ 23C1 DR PRMS (4 times) 2425 ARC LOOP 2439 ARC START (3 times) 245F ARC END (3 times) 247D CD PRMS1 2497 DRAW SAVE 25F8 S RND 2627 S PI 274C S STK LIST 2B59 L NUMERIC 2CCF DEC RPT C 2CD5 DEC STO 1 2CDA NXT DGT 1 2D2B STACK BC 2D3B INT TO FP 2D40 NXT DGT 2 2D55 E SAVE 2D60 E LOOP 2D71 E TST END