UNPKG

@nataliapc/mcp-openmsx

Version:

Model context protocol server for openMSX automation and control

779 lines (445 loc) 293 kB
# 5. ROM BASIC Interpreter Microsoft BASIC has evolved over the years to its present position as the industry standard. It was originally written for the 8080 Microprocessor and even the MSX version is held in 8080 Assembly Language form. This process of continuous development means that there are less Z80-specific instructions than would be expected in a more modern program. It also means that numerous changes have been made and the result is a rather convoluted program. The structure of the Interpreter makes it unlikely that an application program will be able to use its many facilities. However most programs will need to cooperate with it to some extent so this chapter gives a detailed description of its operation. There are four readily identifiable areas of importance within the Interpreter, the one most familiar to any user is the Mainloop ([4134H](#4134h)). This collects numbered lines of text from the console and places them in order in the Program Text Area of memory until a direct statement is received. The Runloop ([4601H](#4601h)) is responsible for the execution of a program. It examines the first token of each program line and calls the appropriate routine to process the remainder of the statement. This continues until no more program text remains, control then returns to the Mainloop. The analysis of numeric or string operands within a statement is performed by the Expression Evaluator ([4C64H](#4c64h)). Each expression is composed of factors, in turn analyzed by the Factor Evaluator ([4DC7H](#4dc7h)), which are linked together by dyadic infix operators. As there are several types of operand, notably line numbers, which cannot form part of an expression in Microsoft BASIC the term "evaluated" is only used to refer to those that can. Otherwise a term such as "computed" will be used. One point to note when examining the Interpreter in detail is that it contains a lot of trick code. The writers seem particularly fond of jumping into the middle of instructions to provide multiple entry points to a routine. As an example take the instruction: 3E D1 Normal: LD A,0D1H When encountered in the usual way this will of course load the accumulator with the value D1H. However if it is entered at "Normal" then it will be executed as a `POP DE` instruction. The Interpreter has many similarly obscure sections. <a name="268ch"></a> Address... 268CH This routine is used by the Expression Evaluator to subtract two double precision operands. The first operand is contained in [DAC](#dac) and the second in [ARG](#arg), the result is returned in [DAC](#dac). The second operand's mantissa sign is inverted and control drops into the addition routine. <a name="269ah"></a> Address... 269AH This routine is used by the Expression Evaluator to add two double precision operands. The first operand is contained in [DAC](#dac) and the second in [ARG](#arg), the result is returned in [DAC](#dac). If the second operand is zero the routine terminates with no action, if the first operand is zero the second operand is copied to [DAC](#dac) ([2F05H](#2f05h)) and the routine terminates. The two exponents are compared, if they differ by more than 10^15 the routine terminates with the larger operand as the result. Otherwise the difference between the two exponents is used to align the mantissae by shifting the smaller one rightwards ([27A3H](#27a3h)), for example: ``` 19.2100 = .1921*10^2 = .192100 + .7436 = .7436*10^0 = .007436 ``` If the two mantissa signs are equal the mantissae are then added ([2759H](#2759h)), if they are different the mantissae are subtracted ([276BH](#276bh)). The exponent of the result is simply the larger of the two original exponents. If an overflow was produced by addition the result mantissa is shifted right one digit (27DBH) and the exponent incremented. If leading zeroes were produced by subtraction the result mantissa is renormalized by shifting left ([2797H](#2797h)). The guard byte is then examined and the result rounded up if the fifteenth digit is equal to or greater than five. <a name="2759h"></a> Address... 2759H This routine adds the two double precision mantissae contained in [DAC](#dac) and [ARG](#arg) and returns the result in [DAC](#dac). Addition commences at the least significant positions, [DAC](#dac)+7 and [ARG](#arg)+7, and proceeds two digits at a time for the seven bytes. <a name="276bh"></a> Address... 276BH This routine subtracts the two double precision mantissae contained in [DAC](#dac) and [ARG](#arg) and returns the result in [DAC](#dac). Subtraction commences at the guard bytes, [DAC](#dac)+8 and [ARG](#arg)+8, and proceeds two digits at a time for the eight bytes. If the result underflows it is corrected by subtracting it from zero and inverting the mantissa sign, for example: 0.17-0.85 = 0.32 = -0.68 </a> <a name="2797h"></a> Address... 2797H This routine shifts the double precision mantissa contained in [DAC](#dac) one digit left. <a name="27a3h"></a> Address... 27A3H This routine shifts a double precision mantissa right. The number of digits to shift is supplied in register A, the address of the mantissa's most significant byte is supplied in register pair HL. The digit count is first divided by two to separate the byte and digit counts. The required number of whole bytes are then shifted right and the most significant bytes zeroed. If an odd number of digits was specified the mantissa is then shifted a further one digit right. <a name="27e6h"></a> Address... 27E6H This routine is used by the Expression Evaluator to multiply two double precision operands. The first operand is contained in [DAC](#dac) and the second in [ARG](#arg), the result is returned in [DAC](#dac). If either operand is zero the routine terminates with a zero result ([2E7DH](#2e7dh)). Otherwise the two exponents are added to produce the result exponent. If this is smaller than 10^-63 the routine terminates with a zero result, if it is greater than 10^63 an "`Overflow error`" is generated ([4067H](#4067h)). The two mantissa signs are then processed to yield the sign of the result, if they are the same the result is positive, if they differ it is negative. Even though the mantissae are in BCD format they are multiplied using the normal binary add and shift method. To accomplish this the first operand is successively multiplied by two ([288AH](#288ah)) to produce the constants X\*80, X\*40, X\*20, X\*10, X\*8, X\*4, X\*2, and X in the [HOLD8](#hold8) buffer. The second operand remains in [ARG](#arg) and [DAC](#dac) is zeroed to function as the product accumulator. Multiplication proceeds by taking successive pairs of digits from the second operand starting with the least significant pair. For each 1 bit in the digit pair the appropriate multiple of the first operand is added to the product. As an example the single multiplication 1823\*96 would produce: 1823*10010110=(1823*80)+(1823*10)+(1823*4)+(1823*2) As each digit pair is completed the product is shifted two digits right. When all seven digit pairs have been processed the routine terminates by renormalizing and rounding up the product (26FAH). The time required for a multiplication depends largely upon the number of 1 bits in the second operand. The worst case, when all the digits are sevens, can take up to 11 ms compared to the average of approximately 7 ms. <a name="288ah"></a> Address... 288AH This routine doubles a double precision mantissa three successive times to produce the products X\*2, X\*4 and X\*8. The address of the mantissa's least significant byte is supplied in register pair DE. The products are stored at successively lower addresses commencing immediately below the operand. <a name="289fh"></a> Address... 289FH This routine is used by the Expression Evaluator to divide two double precision operands. The first operand is contained in [DAC](#dac) and the second in [ARG](#arg), the result is returned in [DAC](#dac). If the first operand is zero the routine terminates with a zero result if the second operand is zero a "`Division by zero`" error is generated ([4058H](#4058h)). Otherwise the two exponents are subtracted to produce the result exponent and the two mantissa signs processed to yield the sign of the result. If they are the same the result is positive, if they differ it is negative. The mantissae are divided using the normal long division method. The second operand is repeatedly subtracted from the first until underflow to produce a single digit of the result. The second operand is then added back to restore the remainder (2761H), the digit is stored in [HOLD](#hold) and the first operand is shifted one digit left. When the first operand has been completely shifted out the result is copied from [HOLD](#hold) to [DAC](#dac) then renormalized and rounded up (2883H). The time required for a division reaches a maximum of approximately 25 ms when the first operand is composed largely of nines and the second operand of ones. This will require the greatest number of subtractions. <a name="2993h"></a> Address... 2993H This routine is used by the Factor Evaluator to apply the "`COS`" function to a double precision operand contained in [DAC](#dac). The operand is first multiplied ([2C3BH](#2c3bh)) by 1/(2\*PI) so that unity corresponds to a complete 360 degree cycle. The operand then has 0.25 (90 degrees) subtracted ([2C32H](#2c32h)), its mantissa sign is inverted (2E8DH) and control drops into the "`SIN`" routine. <a name="29ach"></a> Address... 29ACH This routine is used by the Factor Evaluator to apply the "`SIN`" function to a double precision operand contained in [DAC](#dac). The operand is first multiplied ([2C3BH](#2c3bh)) by 1/(2\*PI) so that unity corresponds to a complete 360 degree cycle. As the function is periodic only the fractional part of the operand is now required. This is extracted by pushing the operand ([2CCCH](#2ccch)) obtaining the integer part ([30CFH](#30cfh)) and copying it to [ARG](#arg) ([2C4DH](#2c4dh)), popping the whole operand to [DAC](#dac) ([2CE1H](#2ce1h)) and then subtracting the integer part ([268CH](#268ch)). The first digit of the mantissa is then examined to determine the operand's quadrant. If it is in the first quadrant it is unchanged. If it is in the second quadrant it is subtracted from 0.5 (180 degrees) to reflect it about the Y axis. If it is in the third quadrant it is subtracted from 0.5 (180 degrees) to reflect it about the X axis. If it is in the fourth quadrant 1.0 (360 degrees) is subtracted to reflect it about both axes. The function is then computed by polynomial approximation ([2C88H](#2c88h)) using the list of coefficients at 2DEFH. These are the first eight terms in the Taylor series X-(X^3/3!)+(X^5/5!)-(X^7/7!) ... with the coefficients multiplied by successive factors of 2\*PI to compensate for the initial scaling. <a name="29fbh"></a> Address... 29FBH This routine is used by the Factor Evaluator to apply the "`TAN`" function to a double precision operand contained in [DAC](#dac). The function is computed using the trigonometric identity TAN(X) = SIN(X)/COS(X). <a name="2a14h"></a> Address... 2A14H This routine is used by the Factor Evaluator to apply the "`ATN`" function to a double precision operand contained in [DAC](#dac). The function is computed by polynomial approximation ([2C88H](#2c88h)) using the list of coefficients at 2E30H. These are the first eight terms in the Taylor series X-(X^3/3)+(X^5/5)-(X^7/7) ... with the coefficients modified slightly to telescope the series. <a name="2a72h"></a> Address... 2A72H This routine is used by the Factor Evaluator to apply the "`LOG`" function to a double precision operand contained in [DAC](#dac). The function is computed by polynomial approximation using the list of coefficients at 2DA5H. <a name="2affh"></a> Address... 2AFFH This routine is used by the Factor Evaluator to apply the "`SQR`" function to a double precision operand contained in [DAC](#dac). The function is computed using the Newton-Raphson process, an equivalent BASIC program is: ``` 10 INPUT"NUMBER";X 20 GUESS=10 30 FOR N=1 To 7 40 GUESS=(GUESS+X/GUESS)/2 50 NEXT N 60 PRINT GUESS 70 PRINT SQR(X) ``` The above program uses a fixed initial guess. While this is accurate over a limited range maximum accuracy will only be attained if the initial guess is near the root. The method used by the ROM is to halve the exponent, with rounding up, and then to divide the first two digits of the operand by four and increment the first digit. <a name="2b4ah"></a> Address... 2B4AH This routine is used by the Factor Evaluator to apply the "`EXP`" function to a double precision operand contained in [DAC](#dac). The operand is first multiplied by 0.4342944819, which is LOG(e) to Base 10, so that the problem becomes computing 10^X rather than e^X. This results in considerable simplification as the integer part can be dealt with easily. The function is then computed by polynomial approximation using the list of coefficients at 2D6BH. <a name="2bdfh"></a> Address... 2BDFH This routine is used by the Factor Evaluator to apply the "`RND`" function to a double precision operand contained in [DAC](#dac). If the operand is zero the current random number is copied to [DAC](#dac) from [RNDX](#rndx) and the routine terminates. If the operand is negative it is copied to [RNDX](#rndx) to set the current random number. The new random number is produced by copying [RNDX](#rndx) to [HOLD](#hold), the constant at 2CF9H to [ARG](#arg), the constant at 2CF1H to [DAC](#dac) and then multiplying (282EH). The fourteen least significant digits of the double length product are copied to [RNDX](#rndx) to form the mantissa of the new random number. The exponent byte in [DAC](#dac) is set to 10^0 to return a value in the range 0 to 1. <a name="2c24h"></a> Address... 2C24H This routine is used by the "`NEW`", "`CLEAR`" and "`RUN`" statement handlers to initialize [RNDX](#rndx) with the constant at 2D01H. <a name="2c2ch"></a> Address... 2C2CH This routine adds the constant whose address is supplied in register pair HL to the double precision operand contained in [DAC](#dac). <a name="2c32h"></a> Address... 2C32H This routine subtracts the constant whose address is supplied in register pair HL from the double precision operand contained in [DAC](#dac). <a name="2c3bh"></a> Address... 2C3BH This routine multiplies the double precision operand contained in [DAC](#dac) by the constant whose address is supplied in register pair HL. <a name="2c41h"></a> Address... 2C41H This routine divides the double precision operand contained in [DAC](#dac) by the constant whose address is supplied in register pair HL. <a name="2c47h"></a> Address... 2C47H This routine performs the relation operation on the double precision operand contained in [DAC](#dac) and the constant whose address is supplied in register pair HL. <a name="2c4dh"></a> Address... 2C4DH This routine copies an eight byte double precision operand from [DAC](#dac) to [ARG](#arg). <a name="2c59h"></a> Address... 2C59H This routine copies an eight byte double precision operand from [ARG](#arg) to [DAC](#dac). <a name="2c6fh"></a> Address... 2C6FH This routine exchanges the eight bytes in [DAC](#dac) with the eight bytes currently on the bottom of the Z80 stack. <a name="2c80h"></a> Address... 2C80H This routine inverts the mantissa sign of the operand contained in [DAC](#dac) (2E8DH). The same address is then pushed onto the stack to restore the sign when the caller terminates. <a name="2c88h"></a> Address... 2C88H This routine generates an odd series based on the double precision operand contained in [DAC](#dac). The series is of the form: X^1*(Kn)+X^3*(Kn-1)+x^5*(Kn-2)+X^5*(Kn-3) ... The address of the coefficient list is supplied in register pair HL. The first byte of the list contains the coefficient count, the double precision coefficients follow with K1 first and Kn last. The even series is generated ([2C9AH](#2c9ah)) and multiplied ([27E6H](#27e6h)) by the original operand. <a name="2c9ah"></a> Address... 2C9AH This routine generates an even series based on the double precision operand contained in [DAC](#dac). The series is of the form: X^0*(Kn)+x^2*(Kn-1)+x^4*(Kn-2)+x^6*(Kn-3) ... The address of the coefficient list is supplied in register pair HL. The first byte of the list contains the coefficient count, the double precision coefficients follow with K1 first and Kn last. The method used to compute the polynomial is known as Horner's method. It only requires one multiplication and one addition per term, the BASIC equivalent is: ``` 10 X=X*X 20 PRODUCT=0 30 RESTORE 100 40 READ COUNT 50 FOR N=1 TO COUNT 60 READ K 70 PRODUCT= ( PRODUCT*X ) +K 80 NEXT N 90 END 100 DATA 8 110 DATA Kn-7 120 DATA Kn-6 130 DATA Kn-5 140 DATA Kn-4 150 DATA Kn-3 160 DATA Kn-2 170 DATA Kn-1 180 DATA Kn ``` The polynomial is processed from the final coefficient through to the first coefficient so that the partial product can be used to save unnecessary operations. <a name="2cc7h"></a> Address... 2CC7H This routine pushes an eight byte double precision operand from [ARG](#arg) onto the Z80 stack. <a name="2ccch"></a> Address... 2CCCH This routine pushes an eight byte double precision operand from [DAC](#dac) onto the Z80 stack. <a name="2cdch"></a> Address... 2CDCH This routine pops an eight byte double precision operand from the Z80 stack into [ARG](#arg). <a name="2ce1h"></a> Address... 2CE1H This routine pops an eight byte double precision operand from the Z80 stack into [DAC](#dac). <a name="2cf1h"></a> Address... 2CF1H This table contains the double precision constants used by the math routines. The first three constants have zero in the exponent position as they are in a special intermediate form used by the random number generator. |ADDRESS|CONSTANT | |ADDRESS|CONSTANT | | |-------|-------------------|-----------|-------|-------------------|---| |2CF1H |.14389820420821 |RND |2DAEH |6.2503651127908 | | |2CF9H |.21132486540519 |RND |2DB6H |-13.682370241503 | | |2D01H |.40649651372358 | |2DBEH |8.5167319872389 | | |2D09H |.43429448190324 |LOG(e) |2DC6H |5 |LOG| |2D11H |.50000000000000 | |2DC7H |1.0000000000000 | | |2D13H |.00000000000000 | |2DCFH |-13.210478350156 | | |2D1BH |1.0000000000000 | |2DD7H |47.925256043873 | | |2D23H |.25000000000000 | |2DDFH |-64.906682740943 | | |2D2BH |3.1622776601684 |SQR(10) |2DE7H |29.415750172323 | | |2D33H |.86858896380650 |2^LOG(e) |2DEFH |8 |SIN| |2D3BH |2.3025850929940 |1/LOG(e) |2DF0H |-.69215692291809 | | |2D43H |1.5707963267949 |PI/2 |2DF8H | 3.8172886385771 | | |2D4BH |.26794919243112 |TAN(PI/12) |2E00H |-15.094499474801 | | |2D53H |1.7320508075689 |TAN(PI/3) |2E08H | 42.058689667355 | | |2D5BH |.52359877559830 |PI/6 |2E10H |-76.705859683291 | | |2D63H |.15915494309190 |1/(2^PI) |2E18H | 81.605249275513 | | |2D6BH |4 |EXP |2E20H |-41.341702240398 | | |2D6CH |1.0000000000000 | |2E28H | 6.2831853071796 | | |2D74H |159.37415236031 | |2E30H |8 |ATN| |2D7CH |2709.3169408516 | |2E31H |-.05208693904000 | | |2D84H |4497.6335574058 | |2E39H |.07530714913480 | | |2D8CH |3 |EXP |2E41H |-.09081343224705 | | |2D8DH |18.312360159275 | |2E49H |.11110794184029 | | |2D95H |831.40672129371 | |2E51H |-.14285708554884 | | |2D9DH |5178.0919915162 | |2E59H |.19999999948967 | | |2DA5H |4 |LOG |2E61H |-.33333333333160 | | |2DA6H |-.71433382153226 | |2E69H |1.0000000000000 | | </a> <a name="2e71h"></a> Address... 2E71H This routine returns the mantissa sign of a Floating Point operand contained in [DAC](#dac). The exponent byte is tested and the result returned in register A and the flags: ``` Zero ....... A=00H, Flag Z,NC Positive ... A=01H, Flag NZ,NC Negative ... A=FFH, Flag NZ,C ``` </a> <a name="2e7dh"></a> Address... 2E7DH This routine simply zeroes the exponent byte in [DAC](#dac). <a name="2e82h"></a> Address... 2E82H This routine is used by the Factor Evaluator to apply the "`ABS`" function to an operand contained in [DAC](#dac). The operand's sign is first checked ([2EA1H](#2ea1h)), if it is positive the routine simply terminates. The operand's type is then checked via the [GETYPR](#getypr) standard routine. If it is a string a "`Type mismatch`" error is generated ([406DH](#406dh)). If it is an integer it is negated ([322BH](#322bh)). If it is a double precision or single precision operand the mantissa sign bit in [DAC](#dac) is inverted. <a name="2e97h"></a> Address... 2E97H This routine is used by the Factor Evaluator to apply the "`SGN`" function to an operand contained in [DAC](#dac). The operand's sign is checked ([2EA1H](#2ea1h)), extended into register pair HL and then placed in [DAC](#dac) as an integer: ``` Zero ....... 0000H Positive ... 0001H Negative ... FFFFH ``` </a> <a name="2ea1h"></a> Address... 2EA1H This routine returns the sign of an operand contained in [DAC](#dac). The operands type is first checked via the [GETYPR](#getypr) standard routine. If it is a string a "`Type mismatch`" error is generated ([406DH](#406dh)). If it is a single precision or double precision operand the mantissa sign is examined ([2E71H](#2e71h)). If it is an integer its value is taken from [DAC](#dac)+2 and translated into the flags shown at [2E71H](#2e71h). <a name="2eb1h"></a> Address... 2EB1H This routine pushes a four byte single precision operand from [DAC](#dac) onto the Z80 stack. <a name="2ec1h"></a> Address... 2EC1H This routine copies the contents of registers C, B, E and D to [DAC](#dac). <a name="2ecch"></a> Address... 2ECCH This routine copies the contents of [DAC](#dac) to registers C, B, E and D. <a name="2ed6h"></a> Address... 2ED6H This routine loads registers C, B, E and D from upwardly sequential locations starting at the address supplied in register pair HL. <a name="2edfh"></a> Address... 2EDFH This routine loads registers E, D, C and B from upwardly sequential locations starting at the address supplied in register pair HL. <a name="2ee8h"></a> Address... 2EE8H This routine copies a single precision operand from [DAC](#dac) to the address supplied in register pair HL. <a name="2eefh"></a> Address... 2EEFH This routine copies any operand from the address supplied in register pair HL to [ARG](#arg). The length of the operand is contained in [VALTYP](#valtyp): 2=Integer, 3=String, 4=Single Precision, 8=Double Precision. <a name="2f05h"></a> Address... 2F05H This routine copies any operand from [ARG](#arg) to [DAC](#dac). The length of the operand is contained in [VALTYP](#valtyp): 2=Integer, 3=String, 4=Single Precision, 8=Double Precision. <a name="2f0dh"></a> Address... 2F0DH This routine copies any operand from [DAC](#dac) to [ARG](#arg). The length of the operand is contained in [VALTYP](#valtyp): 2=Integer, 3=String, 4=Single Precision, 8=Double Precision. <a name="2f21h"></a> Address... 2F21H This routine is used by the Expression Evaluator to find the relation (<>=) between two single precision operands. The first operand is contained in registers C, B, E and D and the second in [DAC](#dac). The result is returned in register A and the flags: ``` Operand 1=Operand 2 ... A=00H, Flag Z,NC Operand 1<Operand 2 ... A=01H, Flag NZ,NC Operand 1>Operand 2 ... A=FFH, Flag NZ,C ``` It should be noted that for relational operators the Expression Evaluator regards maximally negative numbers as small and maximally positive numbers as large. <a name="2f4dh"></a> Address... 2F4DH This routine is used by the Expression Evaluator to find the relation (<>=) between two integer operands. The first operand is contained in register pair DE and the second in register pair HL. The results are as for the single precision version ([2F21H](#2f21h)). <a name="2f83h"></a> Address... 2F83H This routine is used by the Expression Evaluator to find the relation (<>=) between two double precision operands. The first operand is contained in [DAC](#dac) and the second in [ARG](#arg). The results are as for the single precision version ([2F21H](#2f21h)). <a name="2f8ah"></a> Address... 2F8AH This routine is used by the Factor Evaluator to apply the "`CINT`" function to an operand contained in [DAC](#dac). The operand type is first checked via the [GETYPR](#getypr) standard routine, if it is already integer the routine simply terminates. If it is a string a "`Type mismatch`" error is generated ([406DH](#406dh)). If it is a single precision or double precision operand it is converted to a signed binary integer in register pair DE ([305DH](#305dh)) and then placed in [DAC](#dac) as an integer. Out of range values result in an "`Overflow`" error ([4067H](#4067h)). <a name="2fa2h"></a> Address... 2FA2H This routine checks whether [DAC](#dac) contains the single precision operand -32768, if so it replaces it with the integer equivalent 8000H. This step is required during numeric input conversion ([3299H](#3299h)) because of the asymmetric integer number range. <a name="2fb2h"></a> Address... 2FB2H This routine is used by the Factor Evaluator to apply the "`CSNG`" function to an operand contained in [DAC](#dac). The operand's type is first checked via the [GETYPR](#getypr) standard routine, if it is already single precision the routine simply terminates. If it is a string a "`Type mismatch`" error is generated ([406DH](#406dh)). If it is double precision [VALTYP](#valtyp) is changed (3053H) and the mantissa rounded up from the seventh digit (2741H). If the operand is an integer it is converted from binary to a maximum of five BCD digits by successive divisions using the constants 10000, 1000, 100, 10, 1. These are placed in [DAC](#dac) to form the single precision mantissa. The exponent is equal to the number of significant digits in the mantissa. For example if there are five the exponent would be 10^5. <a name="3030h"></a> Address... 3030H This table contains the five constants used by the "`CSNG`" routine: -10000, -1000, -100, -10, -1 <a name="303ah"></a> Address... 303AH This routine is used by the Factor Evaluator to apply the "`CDBL`" function to an operand contained in [DAC](#dac). The operand's type is first checked via the [GETYPR](#getypr) standard routine, if it is already double precision the routine simply terminates. If it is a string a "`Type mismatch`" error is generated ([406DH](#406dh)). If it is an integer it is first converted to single precision (2FC8H), the eight least significant digits are then zeroed and [VALTYP](#valtyp) set to 8. <a name="3058h"></a> Address... 3058H This routine checks that the current operand is a string type, if not a "`Type mismatch`" error is generated ([406DH](#406dh)). <a name="305dh"></a> Address... 305DH This routine is used by the "`CINT`" routine ([2F8AH](#2f8ah)) to convert a BCD single precision or double precision operand into a signed binary integer in register pair DE, it returns Flag C if an overflow has occurred. Successive digits are taken from the mantissa and added to the product starting with the most significant one. After each addition the product is multiplied by ten. The number of digits to process is determined by the exponent, for example five digits would be taken with an exponent of 10^5. Finally the mantissa sign is checked and the product negated (3221H) if necessary. <a name="30beh"></a> Address... 30BEH This routine is used by the Factor Evaluator to apply the "`FIX`" function to an operand contained in [DAC](#dac). The operand's type is first checked via the [GETYPR](#getypr) standard routine, if it is an integer the routine simply terminates. The mantissa sign is then checked ([2E71H](#2e71h)), if it is positive control transfers to the "`INT`" routine ([30CFH](#30cfh)). Otherwise the sign is inverted to positive, the "`INT`" function is performed ([30CFH](#30cfh)) and the sign restored to negative. <a name="30cfh"></a> Address... 30CFH This routine is used by the Factor Evaluator to apply the "`INT`" function to an operand contained in [DAC](#dac). The operand's type is first checked via the [GETYPR](#getypr) standard routine, if it is an integer the routine simply terminates. The number of fractional digits is determined by subtracting the exponent from the type's digit count, 6 for single precision, 14 for double precision. If the mantissa sign is positive these fractional digits are simply zeroed. If the mantissa sign is negative each fractional digit is examined before it is zeroed. If all the digits were previously zero the routine simply terminates. Otherwise -1.0 is added to the operand by the single precision addition routine ([324EH](#324eh)) or the double precision addition routine ([269AH](#269ah)). It should be noted that an operand's type is not normally changed by the "`CINT`" function. <a name="314ah"></a> Address... 314AH This routine multiplies the unsigned binary integers in register pairs BC and DE, the result is returned in register pair DE. The standard shift and add method is used, the product is successively multiplied by two and register pair BC added to it for every 1 bit in register pair DE. The routine is used by the Variable search routine ([5EA4H](#5ea4h)) to compute an element's position within an Array, a "`Subscript out of range`" error is generated (601DH) if an overflow occurs. <a name="3167h"></a> Address... 3167H This routine is used by the Expression Evaluator to subtract two integer operands. The first operand is contained in register pair DE and the second in register pair HL, the result is returned in [DAC](#dac). The second operand is negated (3221H) and control drops into the addition routine. <a name="3172h"></a> Address... 3172H This routine is used by the Expression Evaluator to add two integer operands. The first operand is contained in register pair DE and the second in register pair HL, the result is returned in [DAC](#dac). The signed binary operands are normally just added and placed in [DAC](#dac). However, if an overflow has occurred both operands are converted to single precision (2FCBH) and control transfers to the single precision adder ([324EH](#324eh)). An overflow has occurred when both operands are of the same sign and the result is of the opposite sign, for example: 30000+15000=-20536 </a> <a name="3193h"></a> Address... 3193H This routine is used by the Expression Evaluator to multiply two integer operands. The first operand is contained in register pair DE and the second in register pair HL, the result is returned in [DAC](#dac). The two operand signs are saved temporarily and both operands made positive ([3215H](#3215h)). Multiplication proceeds using the standard binary shift and add method with register pair HL as the product accumulator, register pair BC containing the first operand and register pair DE the second. If the product exceeds 7FFFH at any time during multiplication both operands are converted to single precision (2FCBH) and control transfers to the single precision multiplier ([325CH](#325ch)). Otherwise the initial signs are restored and, if they differ, the product negated before being placed in [DAC](#dac) as an integer (321DH). <a name="31e6h"></a> Address... 31E6H This routine is used by the Expression Evaluator to integer divide (\) two integer operands. The first operand is contained in register pair DE and the second in register pair HL, the result is returned in [DAC](#dac). If the second operand is zero a "`Division by zero`" error is generated ([4058H](#4058h)), otherwise the two operand signs are saved and both operands made positive ([3215H](#3215h)). Division proceeds using the standard binary shift and subtract method with register pair HL containing the remainder, register pair BC the second operand and register pair DE the first operand and the product. When division is complete the initial signs are restored and, if they differ, the product is negated before being placed in [DAC](#dac) as an integer (321DH). <a name="3215h"></a> Address... 3215H This routine is used to make two signed binary integers, in register pairs HL and DE, positive. Both the initial operand signs are returned as a flag in bit 7 of register B: 0=Same, 1=Different. Each operand is then examined and, if it is negative, made positive by subtracting it from zero. <a name="322bh"></a> Address... 322BH This routine is used by the "`ABS`" function to make a negative integer contained in [DAC](#dac) positive. The operand is taken from [DAC](#dac), negated and then placed back in [DAC](#dac) (3221H). If the operand's value is 8000H it is converted to single precision (2FCCH) as there is no integer of value +32768. <a name="323ah"></a> Address... 323AH This routine is used by the Expression Evaluator to "`MOD`" two integer operands. The first operand is contained in register pair DE and the second in register pair HL, the result is returned in [DAC](#dac). The sign of the first operand is saved and the two operands divided ([31E6H](#31e6h)). As the remainder is returned doubled by the division process register pair DE is shifted one place right to restore it. The sign of the first operand is then restored and, if it is negative, the remainder is negated before being placed in [DAC](#dac) as an integer (321DH). <a name="324eh"></a> Address... 324EH This routine is used by the Expression Evaluator to add two single precision operands. The first operand is contained in registers C, B, E, D and the second in [DAC](#dac), the result is returned in [DAC](#dac). The first operand is copied to [ARG](#arg) ([3280H](#3280h)), the second operand is converted to double precision (3042H) and control transfers to the double precision adder ([269AH](#269ah)). <a name="3257h"></a> Address... 3257H This routine is used by the Expression Evaluator to subtract two single precision operands. The first operand is contained in registers C, B, E, D and the second in [DAC](#dac), the result is returned in [DAC](#dac). The second operand is negated (2E8DH) and control transfers to the single precision adder ([324EH](#324eh)). <a name="325ch"></a> Address... 325CH This routine is used by the Expression Evaluator to multiply two single precision operands. The first operand is contained in registers C, B, E, D and the second in [DAC](#dac), the result is returned in [DAC](#dac). The first operand is copied to [ARG](#arg) ([3280H](#3280h)), the second operand is converted to double precision (3042H) and control transfers to the double precision multiplier ([27E6H](#27e6h)). <a name="3265h"></a> Address... 3265H This routine is used by the Expression Evaluator to divide two single precision operands. The first operand is contained in registers C, B, E, D and the second in [DAC](#dac), the result is returned in [DAC](#dac). The first and second operands are exchanged so that the first is in [DAC](#dac) and the second in the registers. The second operand is then copied to [ARG](#arg) ([3280H](#3280h)), the first operand is converted to double precision (3042H) and control transfers to the double precision divider ([289FH](#289fh)). <a name="3280h"></a> Address... 3280H This routine copies the single precision operand contained in registers C, B, E and D to [ARG](#arg) and then zeroes the four least significant bytes. <a name="3299h"></a> Address... 3299H This routine converts a number in textual form to one of the standard internal numeric types, it is used during tokenization and by the "`VAL`", "`INPUT`" and "`READ`" Statement handlers. On entry register pair HL points to the first character of the text string to be converted. On exit register pair HL points to the character following the string, the numeric operand is in [DAC](#dac) and the type code in [VALTYP](#valtyp). Examples of the three types are: <a name="figure41"></a>![][CH05F41] **Figure 41:** Numeric Types in DAC An integer is a sixteen bit binary number in two's complement form, it is stored LSB first, MSB second at [DAC](#dac)+2. An integer can range from 8000H (-32768) to 7FFFH (+32767). A floating point number consists of an exponent byte and a three or seven byte mantissa. The exponent is kept in signed binary form and can range from 01H (-63) through 40H (0) up to 7FH (+63), the special value of 00H is used for the number zero. These exponent values are for a normalized mantissa. The Interpreter presents exponent-form numbers to the user with a leading digit, this results in an asymmetric exponent range of E-64 to E+62. Bit 7 of the exponent byte holds the mantissa sign, 0 for positive and 1 for negative, the mantissa itself is kept in packed BCD form with two digits per byte. It should be noted that the Interpreter uses the contents of [VALTYP](#valtyp) to determine a number's type, not the format of the number itself. Conversion starts by examining the first text character. If this is an "&" control transfers to the special radix conversion routine ([4EB8H](#4eb8h)), if it is a leading sign character it is temporarily saved. Successive numeric characters are then taken and added to the integer product with appropriate multiplications by ten as each new digit is found. If the value of the product exceeds 32767, or a decimal point is found, the product is converted to single precision and any further characters placed directly in [DAC](#dac). If a seventh digit is found the product is changed to double precision, if more than fourteen digits are found the excess digits are read but ignored. Conversion ceases when a non-numeric character is found. If this a type definition character ("%", "#" or "!") the appropriate conversion routine is called and control transfers to the exit point (331EH). If it is an exponent prefix ("E", "e", "D" or "d") one of the conversion routines will also be used and then the following digits converted to a binary exponent in register E. At the exit point (331EH) the product's type is checked via the [GETYPR](#getypr) standard routine. If it is single precision or double precision the exponent is calculated by first subtracting the fractional digit count, in register B, from the total digit count, in register D, to produce the leading digit count. This is then added to any explicitly stated exponent, in register E, and placed at [DAC](#dac)+0 as the exponent. The leading sign character is restored and the product negated if required (2E86H), if the product is integer the routine then terminates. If the product is single precision control terminates by checking for the special value of -32768 ([2FA2H](#2fa2h)). If the product is double precision control terminates by rounding up from the fifteenth digit (273CH). <a name="340ah"></a> Address... 340AH This routine is used by the error handler to display the message " in " ([6678H](#6678h)) followed by the line number supplied in register pair HL ([3412H](#3412h)). <a name="3412h"></a> Address... 3412H This routine displays the unsigned binary integer supplied in register pair HL. The operand is placed in [DAC](#dac) as an integer (2F99H), converted to text (3441H) and then displayed (6677H). <a name="3425h"></a> Address... 3425H This routine converts the numeric operand contained in [DAC](#dac) to textual form in [FBUFFR](#fbuffr). The address of the first character of the resulting text is returned in register pair HL, the text is terminated by a zero byte. The operand is first converted to double precision ([375FH](#375fh)). The BCD digits of the mantissa are then unpacked, converted to ASCII and placed in [FBUFFR](#fbuffr) (36B3H). The position of the decimal point is determined by the exponent, for example: ``` .999*10 ^ +2 = 99.9 .999*10 ^ +1 = 9.99 .999*10 ^ +0 = .999 .999*10 ^ -1 = .0999 ``` If the exponent is outside the range 10^-1 to 10^14 the number is presented in exponential form. In this case the decimal point is placed after the first digit and the exponent is converted from binary and follows the mantissa. An alternative entry point to the routine exists at 3426H for the "`PRINT USING`" statement handler. With this entry point the number of characters to prefix the decimal point is supplied in register B, the number of characters to point fix it in register C and a format byte in register A: <a name="figure42"></a>![][CH05F42] **Figure 42:** Format Byte Operation in this mode is fairly similar to the normal mode but with the addition of extra facilities. Once the operand has been converted to double precision the exponential form will be assumed if bit 0 of the format byte is set. The mantissa is shifted to the right in [DAC](#dac) and rounded up to lose unwanted postfix digits ([377BH](#377bh)). As the mantissa is converted to ASCII (36B3H) commas will be inserted at the appropriate points if bit 6 of the format byte is set. During post-conversion formatting (351CH) unused prefix positions will be filled with asterisks if bit 5 is set, a pound prefix may be added by setting bit 4. Bit 3 enables the "+" sign for positive numbers if set, otherwise a space is used. Bit 2 places any sign at the front if reset and at the back if set. The entry point to the routine at 3441H is used to convert unsigned integers, notably line numbers, to their textual form. For example 9000H, when treated as a normal integer, would be converted to -28672. By using this entry point 36864 would be produced instead. The operand is converted by successive division with the factors 10000, 1000, 100, 10 and 1 and the resulting digits placed in [FBUFFR](#fbuffr) (36DBH). <a name="3710h"></a> Address... 3710H This table contains the five constants used by the numeric output routine: 10000, 1000, 100, 10, 1. <a name="371ah"></a> Address... 371AH This routine is used by the "`BIN`$" function to convert a numeric operand contained in [DAC](#dac) to textual form. Register B is loaded with the group size (1) and control transfers to the general conversion routine (3724H). <a name="371eh"></a> Address... 371EH This routine is used by the "`OCT`$" function to convert a numeric operand contained in [DAC](#dac) to textual form. Register B is loaded with the group size (3) and control transfers to the general conversion routine (3724H). <a name="3722h"></a> Address... 3722H This routine is used by the "`HEX`$" function to convert a numeric operand contained in [DAC](#dac) to textual form. Register B is loaded with the group size (4) and the operand converted to a binary integer in register pair HL ([5439H](#5439h)). Successive groups of 1, 3 or 4 bits are shifted rightwards out of the operand, converted to ASCII digits and placed in [FBUFFR](#fbuffr). When the operand is all zeroes the routine terminates with the address of the first text character in register pair HL, the string is terminated with a zero byte. <a name="3752h"></a> Address... 3752H This routine is used during numeric output to return an operand's digit count in register B and the address of its least significant byte in register pair HL. For single precision B=6 and HL=[DAC](#dac)+3, for double precision B=14 and HL=[DAC](#dac)+7. <a name="375fh"></a> Address... 375FH This routine is used during numeric output to convert the numeric operand in [DAC](#dac) to double precision ([303AH](#303ah)). <a name="377bh"></a> Address... 377BH This routine is used during numeric output to shift the mantissa in [DAC](#dac) rightwards (27DBH), the inverse of the digit count is supplied in register A. The result is then rounded up from the fifteenth digit (2741H). <a name="37a2h"></a> Address... 37A2H This routine is used during numeric output to return the inverse of the fractional digit count in a floating point operand. This is computed by subtracting the exponent from the operand's digit count (6 or 14). <a name="37b4h"></a> Address... 37B4H This routine is used during numeric output to locate the last non-zero digit of the mantissa contained in [DAC](#dac). Its address is returned in register pair HL. <a name="37c8h"></a> Address... 37C8H This routine is used by the Expression Evaluator to exponentiate (^) two single precision operands. The first operand is contained in registers C, B, E, D and the second in [DAC](#dac), the result is returned in [DAC](#dac). The first operand is copied to [ARG](#arg) ([3280H](#3280h)), pushed onto the stack ([2CC7H](#2cc7h)) and exchanged with [DAC](#dac) ([2C6FH](#2c6fh)). The second operand is then popped into [ARG](#arg) and control drops into the double precision exponentiation routine. <a name="37d7h"></a> Address... 37D7H This routine is used by the Expression Evaluator to exponentiate (^) two double precision operands. The first operand is contained in [DAC](#dac) and the second in [ARG](#arg), the result is returned in [DAC](#dac). The result is usually computed using: X^P=EXP(P*LOG(X)) An alternative, much faster, method is possible if the power operand is an integer. This is tested for by extracting the integer part of the operand and comparing for equality with the original value ([391AH](#391ah)). A positive result to this test means that the faster method can be used, this is described below. <a name="383fh"></a> Address... 383FH This routine is used by the Expression Evaluator to exponentiate (^) two integer operands. The first operand is contained in register pair DE and the second in register pair HL, the result is returned in [DAC](#dac). The routine operates by breaking the problem down into simple multiplications: 6^13=6^1101=(6^8)*(6^4)*(6^1) As the power operand is in binary form a simple right shift is sufficient to determine whether a particular intermediate product needs to be included in the result. The intermediate products themselves are obtained by cumulative multiplication of the operand each time the computation loop is traversed. If the product overflows at any time it is converted to single precision. Upon completion the power operand is checked, if it is negative the product is reciprocated as X^-P=1/X^P. <a name="390dh"></a> Address... 390DH This routine is used during exponentiation to multiply two integers ([3193H](#3193h)), it returns Flag NZ if the result has overflowed to single precision. <a name="391ah"></a> Address... 391AH This routine is used during exponentiation to check whether a double precision power operand consists only of an integer part, if so it returns Flag NC. <a name="392eh"></a> Address... 392EH This table of addresses is used by the Interpreter Runloop to find the handler for a statement token. Although not part of the table the associated keywords are included below: |TO |STATEMENT |TO |SATEMENT |TO |STMT | |-------|-----------|-------|-----------|-------|-------| |63EAH |END |00C3H |CLS |5B11H |CIRCLE | |4524H |FOR |51C9H |WIDTH |7980H |COLOR | |6527H |NEXT |485DH |ELSE |5D6EH |DRAW | |485BH |DATA |6438H |TRON |59C5H |PAINT | |4B6CH |INPUT |6439H |TROFF |00C0H |BEEP | |5E9FH |DIM |643EH |SWAP |73E5H |PLAY | |4B9FH |READ |6477H |ERASE |57EAH |PSET | |4880H |LET |49AAH |ERROR |57E5H |PRESET | |47E8H |GOTO |495DH |RESUME |73CAH |SOUND | |479EH |RUN |53E2H |DELETE |79CCH |SCREEN | |49E5H |IF |49B5H |AUTO |7BE2H |VPOKE | |63C9H |RESTORE |5468H |RENUM |7A48H |SPRITE | |47B2H |GOSUB |4718H |DEFSTR |7B37H |VDP | |4821H |RETURN |471BH |DEFINT |7B5AH |BASE | |485DH |REM |471EH |DEFSNG |55A8H |CALL | |63E3H |STOP |4721H |DEFDBL |7911H |TIME | |4A24H |PRINT |4B0EH |LINE |786CH |KEY | |64AFH |CLEAR |6AB7H |OPEN |7E4BH |MAX | |522EH |LIST |7C52H |FIELD |73B7H |MOTOR | |6286H |NEW |775BH |GET |6EC6H |BLOAD | |48E4H |ON |7758H |PUT |6E92H |BSAVE | |401CH |WAIT |6C14H |CLOSE |7C16H |DSKO$ | |501DH |DEF |6B5DH |LOAD |7C1BH |SET | |5423H |POKE |6B5EH |MERGE |7C20H |NAME | |6424H |CONT |6C2FH |FILES |7C25H |KILL | |6FB7H |CSAVE |7C48H |LSET |7C2AH |IPL | |703FH |CLOAD |7C4DH |RSET |7C2FH |COPY | |4016H |OUT |6BA3H |SAVE |7C34H |CMD | |4A1DH |LPRINT |6C2AH |LFILES |7766H |LOCATE | |5229H |LLIST | | | | | <a name="39deh"></a> Address... 39DEH This table of addresses is used by the Factor Evaluator to find the handler for a function token. Although not part of the table the associated keywords are included with the addresses shown below: |TO |FUNCTION |TO |FUNCTION |TO |FUNCTION | |-------|-----------|-------|-----------|-------|-----------| |6861H |LEFT$ |4FCCH |POS |30BEH |FIX | |6891H |RIGHT$ |67FFH |LEN |7940H |STI