| Routines

13147: THE 'CALCULATE' SUBROUTINE

Used by the routine at FP_CALC. This subroutine is used to perform floating-point calculations. These can be considered to be of three types: Binary operations, e.g. addition, where two numbers in floating-point form are added together to give one 'last value'. Unary operations, e.g. sin, where the 'last value' is changed to give the appropriate function result as a new 'last value'. Manipulatory operations, e.g. st_mem, where the 'last value' is copied to the first five bytes of the calculator's memory area. The operations to be performed are specified as a series of data-bytes, the literals, that follow an RST 40 instruction that calls this subroutine. The last literal in the list is always '56' which leads to an end to the whole operation. In the case of a single operation needing to be performed, the operation offset can be passed to the calculator in the B register, and operation '59', the single calculation operation, performed. It is also possible to call this subroutine recursively, i.e. from within itself, and in such a case it is possible to use the system variable BREG as a counter that controls how many operations are performed before returning. The first part of this subroutine is complicated but essentially it performs the two tasks of setting the registers to hold their required values, and to produce an offset, and possibly a parameter, from the literal that is currently being considered. The offset is used to index into the calculator's table of addresses to find the required subroutine address. The parameter is used when the multi-purpose subroutines are called. Note: a floating-point number may in reality be a set of string parameters.
Input
B | Operation offset or counter
CALCULATE | 13147 | CALL STK_PNTRS | Presume a unary operation and therefore set HL to point to the start of the 'last value' on the calculator stack and DE one past this floating-point number (STKEND).
This entry point is used by the routine at series.
GEN_ENT_1 | 13150 | LD A,B | Either transfer a single operation offset to BREG temporarily, or, when using the subroutine recursively, pass the parameter to BREG to be used as a counter.
| 13151 | LD (23655),A
This entry point is used by the routine at series.
GEN_ENT_2 | 13154 | EXX | The return address of the subroutine is stored in HL'. This saves the pointer to the first literal. Entering the calculator here is done whenever BREG is in use as a counter and is not to be disturbed.
| 13155 | EX (SP),HL
| 13156 | EXX
RE_ENTRY | 13157 | LD (23653),DE | A loop is now entered to handle each literal in the list that follows the calling instruction; so first, always set STKEND.
| 13161 | EXX | Go to the alternate register set and fetch the literal for this loop.
| 13162 | LD A,(HL)
| 13163 | INC HL | Make HL' point to the next literal.
This entry point is used by the routine at fp_calc_2.
SCAN_ENT | 13164 | PUSH HL | This pointer is saved briefly on the machine stack. SCAN_ENT is used by fp_calc_2 to find the subroutine that is required.
| 13165 | AND A | Test the A register.
| 13166 | JP P,FIRST_3D | Separate the simple literals from the multi-purpose literals. Jump with literals 0 to 61.
| 13169 | LD D,A | Save the literal in D.
| 13170 | AND 96 | Continue only with bits 5 and 6.
| 13172 | RRCA | Four right shifts make them now bits 1 and 2.
| 13173 | RRCA
| 13174 | RRCA
| 13175 | RRCA
| 13176 | ADD A,124 | The offsets required are 62 to 65, and L will now hold double the required offset.
| 13178 | LD L,A
| 13179 | LD A,D | Now produce the parameter by taking bits 0, 1, 2, 3 and 4 of the literal; keep the parameter in A.
| 13180 | AND 31
| 13182 | JR ENT_TABLE | Jump forward to find the address of the required subroutine.
FIRST_3D | 13184 | CP 24 | Jump forward if performing a unary operation.
| 13186 | JR NC,DOUBLE_A
| 13188 | EXX | All of the subroutines that perform binary operations require that HL points to the first operand and DE points to the second operand (the 'last value') as they appear on the calculator stack.
| 13189 | LD BC,65531
| 13192 | LD D,H
| 13193 | LD E,L
| 13194 | ADD HL,BC
| 13195 | EXX
DOUBLE_A | 13196 | RLCA | As each entry in the table of addresses takes up two bytes the offset produced is doubled.
| 13197 | LD L,A
ENT_TABLE | 13198 | LD DE,13015 | The base address of the table.
| 13201 | LD H,0 | The address of the required table entry is formed in HL, and the required subroutine address is loaded into the DE register pair.
| 13203 | ADD HL,DE
| 13204 | LD E,(HL)
| 13205 | INC HL
| 13206 | LD D,(HL)
| 13207 | LD HL,13157 | The address of RE_ENTRY is put on the machine stack underneath the subroutine address.
| 13210 | EX (SP),HL
| 13211 | PUSH DE
| 13212 | EXX | Return to the main set of registers.
| 13213 | LD BC,(23654) | The current value of BREG is transferred to the B register thereby returning the single operation offset (see compare).
The address of this entry point is found in the table of addresses. It is called via the calculator literal 2 by the routines at BEEP, IF_CMD, FOR, NEXT, CIRCLE, DRAW, CD_PRMS1, S_RND, LET, DEC_TO_FP, e_to_fp, FP_TO_BC, PRINT_FP, series, n_mod_m, exp, ln, get_argt and to_power.
delete | 13217 | RET | An indirect jump to the required subroutine.
The delete subroutine contains only the single 'RET' instruction above. The literal '2' results in this subroutine being considered as a binary operation that is to be entered with a first number addressed by the HL register pair and a second number addressed by the DE register pair, and the result produced again addressed by the HL register pair. The single 'RET' instruction thereby leads to the first number being considered as the resulting 'last value' and the second number considered as being deleted. Of course the number has not been deleted from the memory but remains inactive and will probably soon be overwritten.