Prev: 12719 Up: Map Next: 12947
12820: THE 'INTEGER TRUNCATION TOWARDS ZERO' SUBROUTINE (offset 58)
The address of this routine is found in the table of addresses. It is called via the calculator literal 58 by the routine at int.
This subroutine (say I(x)) returns the result of integer truncation of x, the 'last value', towards zero. Thus I(2.4) is 2 and I(-2.4) is -2. The subroutine returns at once if x is in the form of a 'short integer'. It returns zero if the exponent byte of x is less than 129 (ABS x is less than 1). If I(x) is a 'short integer' the subroutine returns it in that form. It returns x if the exponent byte is 160 or greater (x has no significant non-integral part). Otherwise the correct number of bytes of x are set to zero and, if needed, one more byte is split with a mask.
Input
HL Address of the first byte of the number
truncate 12820 LD A,(HL) Get the exponent byte of x into A.
12821 AND A If A is zero, return since x is already a small integer.
12822 RET Z
12823 CP 129 Compare e, the exponent, to 129.
12825 JR NC,T_GR_ZERO Jump if e is greater than 128.
12827 LD (HL),0 Else, set the exponent to zero; enter 32 into A and jump forward to NIL_BYTES to make all the bits of x be zero.
12829 LD A,32
12831 JR NIL_BYTES
T_GR_ZERO 12833 CP 145 Compare e to 145.
12835 JR NZ,T_SMALL Jump if e not 145.
The next 26 bytes seem designed to test whether x is in fact -65536, i.e. 91 80 00 00 00, and if it is, to set it to 00 FF 00 00 00. This is a mistake. As already stated, the Spectrum system cannot handle this number. The result here is simply to make INT (-65536) return the value -1. This is a pity, since the number would have been perfectly all right if left alone. The remedy would seem to be simply to omit the 28 bytes from 12835 above to 12862 inclusive from the program.
12837 INC HL HL is pointed at the fourth byte of x, where the 17 bits of the integer part of x end after the first bit.
12838 INC HL
12839 INC HL
12840 LD A,128 The first bit is obtained in A, using 128 as a mask.
12842 AND (HL)
12843 DEC HL That bit and the previous 8 bits are tested together for zero.
12844 OR (HL)
12845 DEC HL HL is pointed at the second byte of x.
12846 JR NZ,T_FIRST If already non-zero, the test can end.
12848 LD A,128 Otherwise, the test for -65536 is now completed: 91 80 00 00 00 will leave the zero flag set now.
12850 XOR (HL)
T_FIRST 12851 DEC HL HL is pointed at the first byte of x.
12852 JR NZ,T_EXPNENT If zero reset, the jump is made.
12854 LD (HL),A The first byte is set to zero.
12855 INC HL HL points to the second byte.
12856 LD (HL),255 The second byte is set to 255.
12858 DEC HL HL again points to the first byte.
12859 LD A,24 The last 24 bits are to be zero.
12861 JR NIL_BYTES The jump to NIL_BYTES completes the number 00 FF 00 00 00.
If the exponent byte of x is between 129 and 144 inclusive, I(x) is a 'small integer', and will be compressed into one or two bytes. But first a test is made to see whether x is, after all, large.
T_SMALL 12863 JR NC,X_LARGE Jump with exponent byte 146 or more (it would be better to jump with 145 too).
12865 PUSH DE Save STKEND in DE.
12866 CPL Range 129<=A<=144 becomes 126>=A>=111.
12867 ADD A,145 Range is now 15>=A>=0.
12869 INC HL Point HL at second byte.
12870 LD D,(HL) Second byte to D.
12871 INC HL Point HL at third byte.
12872 LD E,(HL) Third byte to E.
12873 DEC HL Point HL at first byte again.
12874 DEC HL
12875 LD C,0 Assume a positive number.
12877 BIT 7,D Now test for negative (bit 7 set).
12879 JR Z,T_NUMERIC Jump if positive after all.
12881 DEC C Change the sign.
T_NUMERIC 12882 SET 7,D Insert true numeric bit, 1, in D.
12884 LD B,8 Now test whether A>=8 (one byte only) or two bytes needed.
12886 SUB B
12887 ADD A,B Leave A unchanged.
12888 JR C,T_TEST Jump if two bytes needed.
12890 LD E,D Put the one byte into E.
12891 LD D,0 And set D to zero.
12893 SUB B Now 1<=A<=7 to count the shifts needed.
T_TEST 12894 JR Z,T_STORE Jump if no shift needed.
12896 LD B,A B will count the shifts.
T_SHIFT 12897 SRL D Shift D and E right B times to produce the correct number.
12899 RR E
12901 DJNZ T_SHIFT Loop until B is zero.
T_STORE 12903 CALL INT_STORE Store the result on the stack.
12906 POP DE Restore STKEND to DE.
12907 RET Finished.
Large values of x remain to be considered.
T_EXPNENT 12908 LD A,(HL) Get the exponent byte of x into A.
X_LARGE 12909 SUB 160 Subtract 160 from e.
12911 RET P Return on plus - x has no significant non-integral part. (If the true exponent were reduced to zero, the 'binary point' would come at or after the end of the four bytes of the mantissa.)
12912 NEG Else, negate the remainder; this gives the number of bits to become zero (the number of bits after the 'binary point').
Now the bits of the mantissa can be cleared.
NIL_BYTES 12914 PUSH DE Save the current value of DE (STKEND).
12915 EX DE,HL Make HL point one past the fifth byte.
12916 DEC HL HL now points to the fifth byte of x.
12917 LD B,A Get the number of bits to be set to zero in B and divide it by 8 to give the number of whole bytes implied.
12918 SRL B
12920 SRL B
12922 SRL B
12924 JR Z,BITS_ZERO Jump forward if the result is zero.
BYTE_ZERO 12926 LD (HL),0 Else, set the bytes to zero; B counts them.
12928 DEC HL
12929 DJNZ BYTE_ZERO
BITS_ZERO 12931 AND 7 Get A (mod 8); this is the number of bits still to be set to zero.
12933 JR Z,IX_END Jump to the end if nothing more to do.
12935 LD B,A B will count the bits now.
12936 LD A,255 Prepare the mask.
LESS_MASK 12938 SLA A With each loop a zero enters the mask from the right and thereby a mask of the correct length is produced.
12940 DJNZ LESS_MASK
12942 AND (HL) The unwanted bits of (HL) are lost as the masking is performed.
12943 LD (HL),A
IX_END 12944 EX DE,HL Return the pointer to HL.
12945 POP DE Return STKEND to DE.
12946 RET Finished.
Prev: 12719 Up: Map Next: 12947