Prev: 30CA Up: Map Next: 3214
31AF: THE 'DIVISION' OPERATION (offset +05)
The address of this routine is found in the table of addresses. It is called via the calculator literal +05 by the routines at BEEP, DRAW, CD_PRMS1, DEC_TO_FP, e_to_fp, n_mod_m, tan, atn, asn and to_power. It is also called indirectly via fp_calc_2.
This subroutine first prepares the divisor by calling PREP_M_D, reporting arithmetic overflow if it is zero; then it prepares the dividend again calling PREP_M_D, returning if it is zero. Next it fetches the two numbers from the calculator stack and divides their mantissa by means of the usual restoring division, trial subtracting the divisor from the dividend and restoring if there is carry, otherwise adding 1 to the quotient. The maximum precision is obtained for a 4-byte division, and after subtracting the exponents the subroutine exits by joining the later part of multiply.
Input
DE Address of the first byte of the second number (divisor)
HL Address of the first byte of the first number (dividend)
Output
division 31AF CALL RE_ST_TWO Use full floating-point forms.
31B2 EX DE,HL Exchange the pointers.
31B3 XOR A A is set to 0, so that the sign of the first number will go into A.
31B4 CALL PREP_M_D Prepare the divisor and give the report for arithmetic overflow if it is zero.
31B7 JR C,REPORT_6
31B9 EX DE,HL Exchange the pointers.
31BA CALL PREP_M_D Prepare the dividend and return if it is zero (result already zero).
31BD RET C
31BE EXX Exchange the pointers.
31BF PUSH HL Save the next literal address.
31C0 EXX Exchange the registers.
31C1 PUSH DE Save pointer to divisor.
31C2 PUSH HL Save pointer to dividend.
31C3 CALL FETCH_TWO Get the two numbers from the stack.
31C6 EXX Exchange the registers.
31C7 PUSH HL Save M1 and N1 (the exponent bytes) on the machine stack.
31C8 LD H,B Copy the four bytes of the dividend from registers B'C'CB (i.e. M2, M3, M4 and M5; see FETCH_TWO) to the registers H'L'HL.
31C9 LD L,C
31CA EXX
31CB LD H,C
31CC LD L,B
31CD XOR A Clear A and reset the carry flag.
31CE LD B,$DF B will count upwards from -33 to -1 (+DF to +FF), looping on minus and will jump again on zero for extra precision.
31D0 JR DIV_START Jump forward into the division loop for the first trial subtraction.
Now enter the division loop.
DIV_LOOP 31D2 RLA Shift the result left into B'C'CA, shifting out the bits already there, picking up 1 from the carry whenever it is set, and rotating left each byte with carry to achieve the 32-bit shift.
31D3 RL C
31D5 EXX
31D6 RL C
31D8 RL B
31DA EXX
DIV_34TH 31DB ADD HL,HL Move what remains of the dividend left in H'L'HL before the next trial subtraction; if a bit drops into the carry, force no restore and a bit for the quotient, thus retrieving the lost bit and allowing a full 32-bit divisor.
31DC EXX
31DD ADC HL,HL
31DF EXX
31E0 JR C,SUBN_ONLY
DIV_START 31E2 SBC HL,DE Trial subtract divisor in D'E'DE from rest of dividend in H'L'HL; there is no initial carry (see previous step).
31E4 EXX
31E5 SBC HL,DE
31E7 EXX
31E8 JR NC,NO_RSTORE Jump forward if there is no carry.
31EA ADD HL,DE Otherwise restore, i.e. add back the divisor. Then clear the carry so that there will be no bit for the quotient (the divisor 'did not go').
31EB EXX
31EC ADC HL,DE
31EE EXX
31EF AND A
31F0 JR COUNT_ONE Jump forward to the counter.
SUBN_ONLY 31F2 AND A Just subtract with no restore and go on to set the carry flag because the lost bit of the dividend is to be retrieved and used for the quotient.
31F3 SBC HL,DE
31F5 EXX
31F6 SBC HL,DE
31F8 EXX
NO_RSTORE 31F9 SCF One for the quotient in B'C'CA.
COUNT_ONE 31FA INC B Step the loop count up by one.
31FB JP M,DIV_LOOP Loop 32 times for all bits.
31FE PUSH AF Save any 33rd bit for extra precision (the present carry).
31FF JR Z,DIV_START Trial subtract yet again for any 34th bit; the 'PUSH AF' above saves this bit too.
Note: this jump is made to the wrong place. No 34th bit will ever be obtained without first shifting the dividend. Hence important results like 1/10 and 1/1000 are not rounded up as they should be. Rounding up never occurs when it depends on the 34th bit. The jump should have been to DIV_34TH above, i.e. byte +3200 in the ROM should read +DA instead of +E1.
3201 LD E,A Now move the four bytes that form the mantissa of the result from B'C'CA to D'E'DE.
3202 LD D,C
3203 EXX
3204 LD E,C
3205 LD D,B
3206 POP AF Then put the 34th and 33rd bits into B' to be picked up on normalisation.
3207 RR B
3209 POP AF
320A RR B
320C EXX
320D POP BC Restore the exponent bytes M1 and N1.
320E POP HL Restore the pointer to the result.
320F LD A,B Get the difference between the two exponent bytes into A and set the carry flag if required.
3210 SUB C
3211 JP DIVN_EXPT Exit via DIVN_EXPT.
Prev: 30CA Up: Map Next: 3214