Splitting the Atom back exit forward 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:

  1. C8BC - Read (5),Y to the workspace stack.
  2. C231 - Expect and skip past a "'" sign.
  3. C589 - Print the workspace stack in decimal.
  4. C349 - Print the workspace stack in hex.
  5. CD09/F - Input with editing to an input buffer.
  6. 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.

back exit forward