APPENDIX - BASIC programs 1. Program for hex/decimal conversions: A simple program to print out the hex equivalent of any decimal number up to 65535, and vice versa. 10 REM "hex 999 REM "Hex to decimal: 1000 CLS: PRINT AT 3,0; "Input four-figure hex number; program will return decimal equivalent." AT 8,0; "For reverse conversion, press ENTER"'' 1100 DIM h$(4): POKE 23658,8: INPUT "Input hex number: "; LINE h$: POKE 23658,0: IF h$ = " " THEN GO TO 2000: REM The POKES set and unset CAPS LOCK: REM four spaces between the quotes in the last line. 1200 PRINT h$; " hex = "; FN d(h$); " dec": GO TO 1100: REM "FN d(h$) gives decimal value of four hex digits. 1999 REM "Decimal to hex: 2000 CLS: PRINT AT 3,0; "Input integer up to 65535; program will return hex equivalent."; AT 8,0; "To terminate, press ENTER"'' 2100 DIM n$(5): DIM h$(4): POKE 23658,0: INPUT "Input number: "; n$: IF n$=" " THEN STOP: REM "Five spaces between the quotes in last line. 2200 LET n=VAL n$: LET p=4 2300 LET r= n - 16*INT (n/16): LET h$(p) = CHR$ (r+48): IF r > 9 THEN LET h$(p) = CHR$ (r+55) 2400 LET p = p - 1: IF p=0 THEN PRINT n$; " dec = "; h$; " hex": GO TO 2100 2500 LET n = INT (n/16): GO TO 2300 8000 REM "Functions: d(h$) gives decimal value of four hex digits e(h$) gives decimal value of one hex digit 8010 DEF FN d(h$) = FN e(h$(4)) + 16*FN e(h$(3)) + 16**2*FN e(h$(2)) + 16**3*FN e(h$(1)) 8020 DEF FN e(h$) = CODE (h$) - 48*(CODE h$<64) - 55*(CODE h$>64) 9999 SAVE d1 "hex" LINE 1 2. Programs to calculate numbers in FP formats: 2.1 Put any positive number into full FP format; a relatively simple program which first displays the exponent as adecimal number, then each digit of the mantissa also as decimal numbers, ie 10 must be read as Ah, &c. These are the true exponent and mantissa; they must be corrected by adding 80h/128dto the exponent and making a sign bit for the mantissa. 5 REM "fpdec 10 REM "FP format in decimals. 99 REM "Input X: calculate 2**e * n = X such that n is between 0.5 and one. 100 INPUT n: LET e=0: IF NOT n THEN GO TO 600 200 IF n<.5 THEN GO TO 500 300 LET n=n/2: LET e=e+1: IF n<1 THEN GO TO 600 400 GO TO 300 500 LET n=n*2: LET e=e-1: IF n<.5 THEN GO TO 500 599 REM "Print out. 600 CLS: PRINT "Exponent: ";e+128'' "Mantissa bytes:" 700 FOR f=1 TO 4: LET n=n*16: PRINT INT n: LET n=n-INT n: NEXT f 9000 STOP 9999 SAVE d1"fpdec" LINE 9000 2.2 Print decimal numbers or expressions ,positive or negative, in the hex digits of full FP format, and convert FP numbers in either full or small integer format in hex digits back to decimal. A more elaborate program. 5 REM "fpnum 10 CLS: PRINT "To convert decimal numbers to FP format, type RUN 100 and ENTER." 20 PRINT "To convert FP format numbers (full or small integer) to decimal, type RUN 1000 and ENTER." 30 STOP 99 REM "Decimal to FP: input X, and handle zero X. 100 CLS: INPUT "Input numeric expression:"'n: LET m=n: IF NOT n THEN LET hi=0: LET lo=0: GO TO 800 199 REM "Get the sign and absolute value of X: if X has negative or zero true exponent jump on. 200 LET s=SGN n: LET n=ABS n: LET e=0: IF n<.5 THEN GO TO 600 300 IF n<1 THEN GO TO 700 399 REM "Figure true mantissa and exponent for X > 1 400 LET n=n/2: LET e=e+1: IF n<1 THEN GO TO 700 500 GO TO 400 599 REM "X < half 600 LET n=n*2: LET e=e-1: IF n<.5 THEN GO TO 600 699 REM "Convert exponent to FP format in hex digits and put sign bit in mantissa. 700 LET e=e+128: LET hi=INT (e/16): LET lo=e-16*hi: IF s=1 THEN LET n=n-.5000000001: REM "the .5000000001 (eight zeros) is needed to correcta slight inaccuracy in multiplication: PRINT INT (2*.5) will print zero, not one. This is not a Spectrum peculiarity, similaradjustments are sometimes required with much larger computers tocorrect the INT function. I know of no rule for applying the corrections, I just use trial and error. 799 REM "Print out. 800 CLS: PRINT "Decimal", "FP format", FN d$(hi); FN d$(lo);" ";: FOR f=1 TO 11: IF f/3=INT (f/3) THEN PRINT " ";: NEXT f 900 LET n=n*16: PRINT FN d$(INT n);: LET n=n-INT n: NEXT f: STOP 1000 REM "FP to decimal: 1050 POKE 23658,8: REM "this sets CAPS LOCK 1099 REM "Input X and set character counters. Read exponent:subr at 2000 converts hex digit at char to decimal in hdig. 1100 INPUT "Input five-byte FP number (spaces will be ignored):"'f$: LET char=0: LET mcount=11: GO SUB 2000: LET exp=16*(hdig-8): GO SUB 2000: LET exp=exp+hdig: IF exp<>-128 THEN GO TO 1500 1200 REM "Small integers. 1300 GO SUB 2000: LET sign=hdig: LET char=char+1: GO SUB 2000: LET lo=hdig: GO SUB 2000: LET lo=lo*16+hdig: GO SUB 2000: LET hi=hdig: GO SUB 2000: LET hi=hi*16+hdig: LET mant=lo+256*hi: LET exp=32: IF sign THEN LET mant=65535-mant: LET sign=-1: GO TO 1900 1400 LET sign=1: GO TO 1900 1500 REM "Full format: 1600 GO SUB 2000: LET mant=hdig: IF mant>8 THEN LET sign= -1: GO TO 1800 1700 LET sign=1: LET mant=mant+8 1800 GO SUB 2500: REM "Subr 2500 accumulates mantissa value in mant. 1899 REM "Print out. 1900 CLS: PRINT "FP format", f$' "Decimal", 2**(exp-32)*mant*sign: POKE 23658,0: REM CAPS LOCK off 1950 STOP 2000 REM "Subroutine to read hex digit at char into hdig. 2100 LET char=char+1: IF char>LEN f$ THEN LET hdig=0: GO TO 2400 2200 IF f$(char)=" " THEN GO TO 2100 2300 LET hdig=FN h(char) 2400 LET mcount=mcount-1: RETURN 2500 REM "Subroutine to calculate mantissa. 2600 GO SUB 2000: IF mcount THEN LET mant=16*mant+hdig: GO TO 2600 2700 RETURN 2800 REM "FN h(x): converts hex to decimal. 2900 DEF FN h(x) = (CODE f$(x)-48) * (CODE f$(x)<60) + (CODE f$(x)-55) * (CODE f$(x)>60) 3000 REM "FN d$(x): converts decimal to hex. 3100 DEF FN d$(x) = CHR$ ((x+48)*(x<10) + (x+55)*(x>9)) 9999 SAVE d1"fpnum" LINE 9000 3. A program to put constants into "stk-data" format, eg forinclusion in a user list of constants. 5 REM "fpconst 10 CLS: PRINT "Shows decimal numbers (positive or negative) in stk-data format." 20 PRINT "Press any key and enter decimal number or expression." 30 PAUSE 0 100 INPUT "Input decimal number or numeric expression:"'n 1000 REM "Construct "decimal FP number" in n() array. 1010 DIM n(5): LET m=n: IF NOT n THEN GO TO 2000 1020 LET s=SGN n: LET n=ABS n: LET e=0: IF n<.5 THEN GO TO 1060 1030 IF n<1 THEN GO TO 1070 1040 LET n=n/2: LET e=e+1: IF n<1 THEN GO TO 1070 1050 GO TO 1040 1060 LET n=n*2: LET e=e-1: IF n<.5 THEN GO TO 1060 1069 REM "Now e is true exponent, N is true mantissa. 1070 LET n(1)=e+128: FOR f=2 TO 5: LET n=(n+.0000000001) *256: LET n(f)=INT n: LET n=n-n(f): NEXT f: IF s=1 THEN LET n(2)=n(2)-128: REM "The .0000000001 (nine zeros) corrects the INT function. 2000 REM "Convert N to stk-data format. 2010 CLS: PRINT "Decimal",m' "Stk-data 34h",: FOR f=5 TO 1 STEP -1: IF NOT n(f) THEN NEXT f 2020 IF NOT f THEN LET n(2)=176: LET f=3: GO TO 2070 2030 IF f=1 THEN LET f=2: GO TO 2070 2040 LET g=f-2: LET n(1)=n(1)-80: IF n(1)<>64*INT (n(1)/64) THEN GO TO 2060 2049 REM "Print out. 2050 PRINT FN h$(n(1)+64*g);: GO TO 2040 2060 LET n(1)=n(1)+64*g 2070 FOR g=1 TO f: PRINT FN h$(n(g));: NEXT g 2080 STOP 3000 REM "Functions: FN h$(x): makes hex byte ready to print from decimal. FN d$(x): converts decimal digit to hex. 3100 DEF FN h$(x) = FN d$(INT x/16)) + FN d$(x - 16*INT (x/16)) + " " 3200 DEF FN d$(x) = CHR$ (48*(x<10) + 55*(x>9) + x) 9999 SAVE d1"fpconst" LINE 9000 This program gives different representations for the constants "one" and "ten" from those in the constant table at 32C5: - "one" comes out as 31 00 instead of 40 80 00 01 - "ten" comes out as 34 20 instead of 40 B0 00 0A The reason is that the ROM uses the small integer forms as the basis for figuring the "stk-data" forms. I cannot see anyuseful purpose served by this, and the forms come out two bytes longer. 4. Programs for reading ROM and RAM: 4.1 A very simple general-purpose reader, which can be addedto existing programs ad hoc for debugging etc: it can even be used as a direct command: 100 INPUT x: CLS: FOR f=x to 70000: PRINT f, PEEK f: NEXT f 4.2 An obvious expansion of this would make it print out in hex, using FN h$(f) from one of the above programs. 4.3 Another expansion, useful for reading messages, prints out the character represented by the code: 100 INPUT x: CLS: FOR f=x to 70000: PRINT f; TAB 7; PEEK f,: IF PEEK f > 32 THEN PRINT CHR$ PEEK f;: REM "Some character codes less than 32 would give errorreports. 200 PRINT: NEXT f