Splitting the Atom |
|
page 41 to 44 |
CHAPTER 6
WORKING EXAMPLES USING THE ROM ROUTINES
For normal interpreting us there are six major subroutines
that are most useful:
- C8BC - Read (5),Y to the workspace stack.
- C231 - Expect and skip past a "'" sign.
- C589 - Print the workspace stack in decimal.
- C349 - Print the workspace stack in hex.
- CD09/F - Input with editing to an input buffer.
- F7D1 - Machine code version of PRINT
".....".
Further, the best way to end any machine code routine is JMP
#C55B, rather than using RTS.
The examples below use these and other routines to show how they
can be incorporated into your own systems.
1. To print out messages on the
screen.
100 DIM P-1
110 M=P
120 [;JSR #F7D1;] CALL IN-LINE PRINTER
130 $P="THIS IS A MESSAGE"
140 P=P+LEN P
150 [;NOP TERMINATE PRINTER WITH A NEGATIVE
CHARACTER SUCH A "NOP"
160 JSR #FFED EXECUTE CR LF
170 RTS;]
180 DO;LINK M; UNTIL 0 TEST IT OUT
2. To copy a value on the
workspace stack to an integer variable.
100 DIM P-1;M=P;[
110 LDY@ CH"N"-40 COPIES WORKSPACE STACK VALUE IN
120 LDX@ #FF #16,25,34,43 TO INTEGER
130 JSR #CA37;] VARIABLE N
140 ?16 = 9; LINK M; PRINT N; E.
3. To print out the value of one
of the integer variables
100 DIM P-1;M=P;[
110 LDY@ CH"N"-40 FETCH VARIABLE N TO THE
120 LDX@ 1
130 JSR #CE83; WORKSPACE STACK
140 JSR #C589;] PRINT WORKSPACE STACK AS DECIMAL
150 LET N=20; LINK M; E.
4. For those with DISATOM, using
x to pass on a number that fills the screen
10 DIM JJ1;JJ0=-1;JJ1=-1
20 FOR X = 0 TO 1 TWO PASSES
30 P=#3800 ASSEMBLE AT 3800
40 [ START ASSEMBLING
50 JSR #C8BC READ VALUE AFTER x TO WORKSPACE STACK
60 JSR #C4E4 CHECK FOR RUBBISH , <CR>, OR ; OK
70 LDA @0; STA 4 RESET WORKSPACE STACK POINTER
80 LDA #16; LDX @0 PUT VALUE INTO ALL SCREEN RAM
90:JJ0
100 STA #8000,X
110 STA #8100,X
120 INX; BNE JJ0
130 JMP #C55B;] BACK TO INTERPRETER
140 NEXT; END
N.B: the x command must be space away from the line number if
it is the first command in a line, or the interpreter will
mistake it for a label. All x routine must end in JMP #C55B.
A BASIC program to use the above machine code is:
10 !#180=#3B00
20 F. A=0 TO 255
30 x A
40 F.I=1 TO 60; WAIT;N
50 N.A
60 E.
5. To INPUT numbers into your
routines
100 DIM P-1;M=P;[
110 JSR #CD09 INPUT WITH EDITING TO #140 BUFFER
120 LDY @1; STY 6 120-140, POINT (5),3 AT #140
130 DEY; STY 3
140 LDA @#40;STA 5
150 JSR #C8BC READ #140 BUFFER TO WORKSPACE STACK
160 JSR #C589 PRINT WORKSPACE AS DECIMAL IN FIELD @
170 RTS;]
180 LINK M; E. TEST IT
NOTE: This input allows decimal or # prefixed hexadecimal.
Repeated calls to C8BC should be prefixed with LDA @0;STA 4 to
reset the workspace stack. Unless (5),3 is PUSHed before entry to
this routine, then PULLed at the end, it will exit to direct
mode.
6. To INPUT hex numbers into
your routines
100 DIM P-1;M=P;[
110 LDA@ CH"#"-40 PROMPT WITH CHARACTER #
120 JSR #CD0F INPUT WITH EDIT TO #100 BUFFER
130 LDY @0 RESET Y
140 LDX @#80 READ #100 BUFFER AS HEX, STOR TO
150 JSR #F893 VECTOR X POINTS A - HERE #80
160 JSR #F7F1 PRINT VECTOR X POINTS AT AS HEX
170 RTS; ]
180 LINK M; E. TEST IT
NOTE: F893 stores the #100 buffer as a two-byte vector in page
0, which is pointed at by X on entry to the routine. The
accumulator is stored in the third byte, so P.!#80 gives a
strange result.
7. Hex printer
100 DIM P-1;M=P;[
110 JSR #CD09 INPUT WITH EDIT TO #140 ? PROMPT
120 LDY @0; STY 3 SET UP VECTOR (5),Y WHERE
130 INY; STY 6 Y=?3
140 LDA @#40; STA 5 TO POINT AT #140
150 JSR #C8BC READ (5),Y TO WORKSPACE STACK
160 JSR #C349 PRINT WORKSPACE STACK IN HEX
170 RTS;]
180 LINK M; E. TEST IT
8. Inverting the screen
10 DIM JJ2;F.I=0 TO 2; JJI=-1; N.; F. X= 0 TO 1; P=#28000;[
20:JJ0 LDY @0; JSR #FE66 SYNC TO TV FLYBACK
30:JJ1 LDA #8000,Y
40 EOR @#80; STA #8000,Y DO TOP OF SCREEN
50 INY; BNE JJ1
60 JSR #FE6B CHECK STILL IN FLYBACK OR WAIT
70:JJ2 LDA #8100,Y DO LOWER SCREEN
90 INY; BNE JJ2
100 RTS;]
110 NEXT X
120 DO; LINK JJ0 TEST IT
130 F. X=1 TO 30; WAIT; N.
140 UNTIL 0
9. Unsigned Multiply: executes
(R)=(M)*Acc
10 R=#80 2-BYTE RESULT
20 M=#82 2-BYTE MULTIPLIER
30 DIM JJ2; F.I= 0 TO 2; JJ1=-1;N.; F.X=0 TO 1; P=#2800;[
40:JJ0 PHA
50 LDA @0; STA R; STA R+1
60 PLA; LDX @8
70:JJ1 CLC
80 ROL R; ROL R+1
90 ASL A; BCC JJ2
100 PHA; CLC
110 LDA R; ADC M; STA R
120 LDA R+1; ADC M+1; STA R+1
130 PLA
140:JJ2 DEX; BNE JJ1
150 RTS;]
160 NEXT X
170 !M=#100; A=#B TEST IT
180 LINK JJ0
190 PRINT &(!R&#FFFF);E.
10. Unsigned divide: execute
(D)=(D)/V
10 D=#80 2-BYTE DIVIDEND
20 V=#82 2-BYTE DIVISOR
30 R=#83 2-BYTE REMAINDER
40 DIM JJ5; F.I= 0 TO 5; JJ1=-1;N.; F.X=0 TO 1; P=#2800;[
50:JJ0 LDA @0; STA R
60 LDX @#11; BNE JJ2
70:JJ1 SEC
80 LDA R; SBC V; BPL JJ3
90:JJ2 CLC; BCC JJ4
100:JJ3 STA R; SEC
110:JJ4 ROL D; ROL D+1
120 DEX; BEQ JJ5
130 ROL R; JMP JJ1
140:JJ5 RTS;]
150 NEXT X
160 !D=#400; ?V=#21 TEST IT
170 LINK JJ0
190 PRINT &(!D&#FFFF), ?R
190 END
11. Cyclic redundancy check
(CRC)
Has many uses, but for example, it the CRC is known for a
program, it should give the same result again after reloading
from tape. See chapter 7 for application.
100 DIM JJ4; p.$21
110 F.I=0 TO 4; JJ1=#FFFF;N.
120 F.I=0 TO 2; DIM P -1; M=P;[
130 JSR #F7D1;]
140 $P="START ADDRE ";P=P+LEN P;[
150 NOP
160 LDA @CH"#"; JSR #CD0F
170 LDY @0; LDX @#90; JSR #F893
180 JSR #F7D1;]
190 $P=" END ADDR "; P=P+LEN P;[
200 NOP
210 LDY @0; LDX @#92; JSR #F893
220 LDY @0; STY #A0; STY #A1
240:JJ1 JSR JJ2
250 LDX @#90; JSR #FA08
260 BNE JJ1
270 JSR JJ2
280 JSR #F7D1;]
290 $P="SIGNATURE IS ";P=P+LEN P;[
300 NOP
310 LDX @#A0; JSR #F7F1; JSR #FFED
320 JMP #C55B
330:JJ2 LDX @8; CLC
340 LDA (#90),Y
350:JJ3 LSR A; ROL #A0; ROL #A1; BCC JJ4
360 PHA
370 LDA #A0; EOR @#2D; STA #A0
380 PLA
390:JJ4 DEX; BNE JJ3
400 RTS
410 ];P.$6;P."M/C CODE IS AT " M; LINK M; E.
|