Routines |
Prev: 31AF | Up: Map | Next: 3293 |
The address of this routine is found in the table of addresses. It is called via the calculator literal +3A 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 +81 (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 +A0 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.
|
||||||||
truncate | 3214 | LD A,(HL) | Get the exponent byte of x into A. | |||||
3215 | AND A | If A is zero, return since x is already a small integer. | ||||||
3216 | RET Z | |||||||
3217 | CP $81 | Compare e, the exponent, to +81. | ||||||
3219 | JR NC,T_GR_ZERO | Jump if e is greater than +80. | ||||||
321B | LD (HL),$00 | Else, set the exponent to zero; enter +20 into A and jump forward to NIL_BYTES to make all the bits of x be zero. | ||||||
321D | LD A,$20 | |||||||
321F | JR NIL_BYTES | |||||||
T_GR_ZERO | 3221 | CP $91 | Compare e to +91. | |||||
3223 | JR NZ,T_SMALL | Jump if e not +91. | ||||||
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 3223 above to 323E inclusive from the program.
|
||||||||
3225 | 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. | ||||||
3226 | INC HL | |||||||
3227 | INC HL | |||||||
3228 | LD A,$80 | The first bit is obtained in A, using +80 as a mask. | ||||||
322A | AND (HL) | |||||||
322B | DEC HL | That bit and the previous 8 bits are tested together for zero. | ||||||
322C | OR (HL) | |||||||
322D | DEC HL | HL is pointed at the second byte of x. | ||||||
322E | JR NZ,T_FIRST | If already non-zero, the test can end. | ||||||
3230 | LD A,$80 | Otherwise, the test for -65536 is now completed: 91 80 00 00 00 will leave the zero flag set now. | ||||||
3232 | XOR (HL) | |||||||
T_FIRST | 3233 | DEC HL | HL is pointed at the first byte of x. | |||||
3234 | JR NZ,T_EXPNENT | If zero reset, the jump is made. | ||||||
3236 | LD (HL),A | The first byte is set to zero. | ||||||
3237 | INC HL | HL points to the second byte. | ||||||
3238 | LD (HL),$FF | The second byte is set to +FF. | ||||||
323A | DEC HL | HL again points to the first byte. | ||||||
323B | LD A,$18 | The last 24 bits are to be zero. | ||||||
323D | JR NIL_BYTES | The jump to NIL_BYTES completes the number 00 FF 00 00 00. | ||||||
If the exponent byte of x is between +81 and +90 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 | 323F | JR NC,X_LARGE | Jump with exponent byte +92 or more (it would be better to jump with +91 too). | |||||
3241 | PUSH DE | Save STKEND in DE. | ||||||
3242 | CPL | Range 129<=A<=144 becomes 126>=A>=111. | ||||||
3243 | ADD A,$91 | Range is now 15>=A>=0. | ||||||
3245 | INC HL | Point HL at second byte. | ||||||
3246 | LD D,(HL) | Second byte to D. | ||||||
3247 | INC HL | Point HL at third byte. | ||||||
3248 | LD E,(HL) | Third byte to E. | ||||||
3249 | DEC HL | Point HL at first byte again. | ||||||
324A | DEC HL | |||||||
324B | LD C,$00 | Assume a positive number. | ||||||
324D | BIT 7,D | Now test for negative (bit 7 set). | ||||||
324F | JR Z,T_NUMERIC | Jump if positive after all. | ||||||
3251 | DEC C | Change the sign. | ||||||
T_NUMERIC | 3252 | SET 7,D | Insert true numeric bit, 1, in D. | |||||
3254 | LD B,$08 | Now test whether A>=8 (one byte only) or two bytes needed. | ||||||
3256 | SUB B | |||||||
3257 | ADD A,B | Leave A unchanged. | ||||||
3258 | JR C,T_TEST | Jump if two bytes needed. | ||||||
325A | LD E,D | Put the one byte into E. | ||||||
325B | LD D,$00 | And set D to zero. | ||||||
325D | SUB B | Now 1<=A<=7 to count the shifts needed. | ||||||
T_TEST | 325E | JR Z,T_STORE | Jump if no shift needed. | |||||
3260 | LD B,A | B will count the shifts. | ||||||
T_SHIFT | 3261 | SRL D | Shift D and E right B times to produce the correct number. | |||||
3263 | RR E | |||||||
3265 | DJNZ T_SHIFT | Loop until B is zero. | ||||||
T_STORE | 3267 | CALL INT_STORE | Store the result on the stack. | |||||
326A | POP DE | Restore STKEND to DE. | ||||||
326B | RET | Finished. | ||||||
Large values of x remain to be considered.
|
||||||||
T_EXPNENT | 326C | LD A,(HL) | Get the exponent byte of x into A. | |||||
X_LARGE | 326D | SUB $A0 | Subtract +A0 from e. | |||||
326F | 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.) | ||||||
3270 | 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 | 3272 | PUSH DE | Save the current value of DE (STKEND). | |||||
3273 | EX DE,HL | Make HL point one past the fifth byte. | ||||||
3274 | DEC HL | HL now points to the fifth byte of x. | ||||||
3275 | 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. | ||||||
3276 | SRL B | |||||||
3278 | SRL B | |||||||
327A | SRL B | |||||||
327C | JR Z,BITS_ZERO | Jump forward if the result is zero. | ||||||
BYTE_ZERO | 327E | LD (HL),$00 | Else, set the bytes to zero; B counts them. | |||||
3280 | DEC HL | |||||||
3281 | DJNZ BYTE_ZERO | |||||||
BITS_ZERO | 3283 | AND $07 | Get A (mod 8); this is the number of bits still to be set to zero. | |||||
3285 | JR Z,IX_END | Jump to the end if nothing more to do. | ||||||
3287 | LD B,A | B will count the bits now. | ||||||
3288 | LD A,$FF | Prepare the mask. | ||||||
LESS_MASK | 328A | SLA A | With each loop a zero enters the mask from the right and thereby a mask of the correct length is produced. | |||||
328C | DJNZ LESS_MASK | |||||||
328E | AND (HL) | The unwanted bits of (HL) are lost as the masking is performed. | ||||||
328F | LD (HL),A | |||||||
IX_END | 3290 | EX DE,HL | Return the pointer to HL. | |||||
3291 | POP DE | Return STKEND to DE. | ||||||
3292 | RET | Finished. |
Prev: 31AF | Up: Map | Next: 3293 |