Routines 
Prev: 300F  Up: Map  Next: 30A9 
The address of this routine is found in the table of addresses. It is called via the calculator literal +0F by the routines at BEEP, NEXT, CIRCLE, DRAW, CD_PRMS1, S_RND, DEC_TO_FP, INT_TO_FP, FP_TO_BC, series, exp, ln, get_argt, sin, atn and asn. It is also called indirectly via fp_calc_2, and the routine at subtract continues here.
The first of three major arithmetical subroutines, this subroutine carries out the floatingpoint addition of two numbers, each with a 4byte mantissa and a 1byte exponent. In these three subroutines, the two numbers at the top of the calculator stack are added/multiplied/divided to give one number at the top of the calculator stack, a 'last value'.
HL points to the second number from the top, the augend/multiplier/dividend. DE points to the number at the top of the calculator stack, the addend/multiplicand/divisor. Afterwards HL points to the resultant 'last value' whose address can also be considered to be STKEND5.
But the addition subroutine first tests whether the 2 numbers to be added are 'small integers'. If they are, it adds them quite simply in HL and BC, and puts the result directly on the stack. No two's complementing is needed before or after the addition, since such numbers are held on the stack in two's complement form, ready for addition.


addition  3014  LD A,(DE)  Test whether the first bytes of both numbers are zero.  
3015  OR (HL)  
3016  JR NZ,FULL_ADDN  If not, jump for full addition.  
3018  PUSH DE  Save the pointer to the second number.  
3019  INC HL  Point to the second byte of the first number and save that pointer too.  
301A  PUSH HL  
301B  INC HL  Point to the less significant byte.  
301C  LD E,(HL)  Fetch it in E.  
301D  INC HL  Point to the more significant byte.  
301E  LD D,(HL)  Fetch it in D.  
301F  INC HL  Move on to the second byte of the second number.  
3020  INC HL  
3021  INC HL  
3022  LD A,(HL)  Fetch it in A (this is the sign byte).  
3023  INC HL  Point to the less significant byte.  
3024  LD C,(HL)  Fetch it in C.  
3025  INC HL  Point to the more significant byte.  
3026  LD B,(HL)  Fetch it in B.  
3027  POP HL  Fetch the pointer to the sign byte of the first number; put it in DE, and the number in HL.  
3028  EX DE,HL  
3029  ADD HL,BC  Perform the addition: result in HL.  
302A  EX DE,HL  Result to DE, sign byte to HL.  
302B  ADC A,(HL)  Add the sign bytes and the carry into A; this will detect any overflow.  
302C  RRCA  
302D  ADC A,$00  A nonzero A now indicates overflow.  
302F  JR NZ,ADDN_OFLW  Jump to reset the pointers and to do full addition.  
3031  SBC A,A  Define the correct sign byte for the result.  
3032  LD (HL),A  Store it on the stack.  
3033  INC HL  Point to the next location.  
3034  LD (HL),E  Store the low byte of the result.  
3035  INC HL  Point to the next location.  
3036  LD (HL),D  Store the high byte of the result.  
3037  DEC HL  Move the pointer back to address the first byte of the result.  
3038  DEC HL  
3039  DEC HL  
303A  POP DE  Restore STKEND to DE.  
303B  RET  Finished.  
Note that the number 65536 can arise here in the form 00 FF 00 00 00 as the result of the addition of two smaller negative integers, e.g. 65000 and 536. It is simply stacked in this form. This is a mistake. The Spectrum system cannot handle this number.
Most functions treat it as zero, and it is printed as 1E38, obtained by treating is as 'minus zero' in an illegitimate format.
One possible remedy would be to test for this number at about byte 3032 and, if it is present, to make the second byte +80 and the first byte +91, so producing the full fivebyte floatingpoint form of the number, i.e. 91 80 00 00 00, which causes no problems. See also the remarks in 'truncate'.


ADDN_OFLW  303C  DEC HL  Restore the pointer to the first number.  
303D  POP DE  Restore the pointer to the second number.  
FULL_ADDN  303E  CALL RE_ST_TWO  Restack both numbers in full fivebyte floatingpoint form.  
The full addition subroutine first calls PREP_ADD for each number, then gets the two numbers from the calculator stack and puts the one with the smaller exponent into the addend position. It then calls SHIFT_FP to shift the addend up to 32 decimal places right to line it up for addition. The actual addition is done in a few bytes, a single shift is made for carry (overflow to the left) if needed, the result is two's complemented if negative, and any arithmetic overflow is reported; otherwise the subroutine jumps to TEST_NORM to normalise the result and return it to the stack with the correct sign bit inserted into the second byte.


3041  EXX  Exchange the registers.  
3042  PUSH HL  Save the next literal address.  
3043  EXX  Exchange the registers.  
3044  PUSH DE  Save pointer to the addend.  
3045  PUSH HL  Save pointer to the augend.  
3046  CALL PREP_ADD  Prepare the augend.  
3049  LD B,A  Save its exponent in B.  
304A  EX DE,HL  Exchange the pointers.  
304B  CALL PREP_ADD  Prepare the addend.  
304E  LD C,A  Save its exponent in C.  
304F  CP B  If the first exponent is smaller, keep the first number in the addend position; otherwise change the exponents and the pointers back again.  
3050  JR NC,SHIFT_LEN  
3052  LD A,B  
3053  LD B,C  
3054  EX DE,HL  
SHIFT_LEN  3055  PUSH AF  Save the larger exponent in A.  
3056  SUB B  The difference between the exponents is the length of the shift right.  
3057  CALL FETCH_TWO  Get the two numbers from the stack.  
305A  CALL SHIFT_FP  Shift the addend right.  
305D  POP AF  Restore the larger exponent.  
305E  POP HL  HL is to point to the result.  
305F  LD (HL),A  Store the exponent of the result.  
3060  PUSH HL  Save the pointer again.  
3061  LD L,B  M4 to H and M5 to L (see FETCH_TWO).  
3062  LD H,C  
3063  ADD HL,DE  Add the two right bytes.  
3064  EXX  N2 to H' and N3 to L' (see FETCH_TWO).  
3065  EX DE,HL  
3066  ADC HL,BC  Add left bytes with carry.  
3068  EX DE,HL  Result back in D'E'.  
3069  LD A,H  Add H', L' and the carry; the resulting mechanisms will ensure that a single shift right is called if the sum of 2 positive numbers has overflowed left, or the sum of 2 negative numbers has not overflowed left.  
306A  ADC A,L  
306B  LD L,A  
306C  RRA  
306D  XOR L  
306E  EXX  
306F  EX DE,HL  The result is now in DED'E'.  
3070  POP HL  Get the pointer to the exponent.  
3071  RRA  The test for shift (H', L' were +00 for positive numbers and +FF for negative numbers).  
3072  JR NC,TEST_NEG  
3074  LD A,$01  A counts a single shift right.  
3076  CALL SHIFT_FP  The shift is called.  
3079  INC (HL)  Add 1 to the exponent; this may lead to arithmetic overflow.  
307A  JR Z,ADD_REP_6  
TEST_NEG  307C  EXX  Test for negative result: get sign bit of L' into A (this now correctly indicates the sign of the result).  
307D  LD A,L  
307E  AND $80  
3080  EXX  
3081  INC HL  Store it in the second byte position of the result on the calculator stack.  
3082  LD (HL),A  
3083  DEC HL  
3084  JR Z,GO_NC_MLT  If it is zero, then do not two's complement the result.  
3086  LD A,E  Get the first byte.  
3087  NEG  Negate it.  
3089  CCF  Complement the carry for continued negation, and store byte.  
308A  LD E,A  
308B  LD A,D  Get the next byte.  
308C  CPL  One's complement it.  
308D  ADC A,$00  Add in the carry for negation.  
308F  LD D,A  Store the byte.  
3090  EXX  Proceed to get next byte into the A register.  
3091  LD A,E  
3092  CPL  One's complement it.  
3093  ADC A,$00  Add in the carry for negation.  
3095  LD E,A  Store the byte.  
3096  LD A,D  Get the last byte.  
3097  CPL  One's complement it.  
3098  ADC A,$00  Add in the carry for negation.  
309A  JR NC,END_COMPL  Done if no carry.  
309C  RRA  Else, get .5 into mantissa and add 1 to the exponent; this will be needed when two negative numbers add to give an exact power of 2, and it may lead to arithmetic overflow.  
309D  EXX  
309E  INC (HL)  
ADD_REP_6  309F  JP Z,REPORT_6  Give the error if required.  
30A2  EXX  
END_COMPL  30A3  LD D,A  Store the last byte.  
30A4  EXX  
GO_NC_MLT  30A5  XOR A  Clear A and the carry flag.  
30A6  JP TEST_NORM  Exit via TEST_NORM. 
Prev: 300F  Up: Map  Next: 30A9 