Porting Sweet 16 by Carsten Strotmann (carsten@strotmann.de)

[Up to Source Code Repository]



This material was provided by Carsten Strotmann, who has built a working Atari Port of Sweet 16.

This text focuses only on the task of porting Sweet 16 to another 6502 based computer. Information on the useage and the interals of Sweet 16 can be found in the documentation by Steve Wozniak and the article by Dick Sedgewick.

Porting Sweet 16 is easy, if you know what to take into account. There are three main issues:

the location of the zero page registers the base address of the code in memory the save and restore routines

Let's start with the zero page registers

Sweet 16 needs 32 zero page addresses for the 16 registers (R0-R15). In the original Apple Version this registers are from $0 to $1F,in the ATARI Version the locations $E0-$FF are used. You can place this registers anywhere in the zeropage, but it have to be a contiguous range.

The base address of the code

Sweet 16 uses a tricky indirect 8-Bit jump to access the routines for each opcode. This saves some space in the code. But for this hack to work, some precaution have to be taken for the code. All code from the label "SET" to the label "RTN" have to be assembled in one 6502 Page ($100/256 Bytes). If you mind this, everything should work fine.

The "save" and "restore" routines

The Apple ][ Version of Sweet 16 uses the ROM-internal "save" and "restore" routines to save and restore all processor registers and flags. If your system has such routines in ROM, fine, just use them. If not, you have to add these routines to your programm. Here is a template:

;------------------------------ SAVE STA ACC STX XREG STY YREG PHP PLA STA STATUS CLD RTS ;------------------------------ RESTORE LDA STATUS PHA LDA ACC LDX XREG LDY YREG PLP RTS ;------------------------------- ACC .BYTE 0 XREG .BYTE 0 YREG .BYTE 0 STATUS .BYTE 0

Article 1684 of comp.sys.apple2.programmer: Newsgroups: comp.sys.apple2.programmer Path: amdahl.uts.amdahl.com!amdahl!amd!decwrl!sdd.hp.com!elroy.jpl.nasa.gov!swrinde!ihnp4.ucsd.edu!library.ucla.edu!csulb.edu!csus.edu!netcom.com!sheldon From: sheldon@netcom.com (Sheldon Simms) Subject: Source code (Sweet 16) Message-ID: <sheldonCLz3qM.85r@netcom.com> Organization: NETCOM On-line Communication Services (408 241-9760 guest) Date: Tue, 1 Mar 1994 06:37:33 GMT Lines: 264 Well maybe this should go to comp.sources.apple2 but it's not too long and in my mind it's part of the thread on learning assembly language programming. It's an opportunity to learn from Woz himself. -Sheldon ******************************** * * * APPLE-II PSEUDO MACHINE * * INTERPRETER * * * * COPYRIGHT (C) 1977 * * APPLE COMPUTER, INC * * * * ALL RIGHTS RESERVED * * * * S. WOZNIAK * * * ******************************** * * * TITLE: SWEET 16 INTERPRETER * * * ******************************** R0L EQU $0 R0H EQU $1 R14H EQU $1D R15L EQU $1E R15H EQU $1F SAVE EQU $FF4A RESTORE EQU $FF3F ORG $F689 AST 32 JSR SAVE ;PRESERVE 6502 REG CONTENTS PLA STA R15L ;INIT SWEET16 PC PLA ;FROM RETURN STA R15H ;ADDRESS SW16B JSR SW16C ;INTERPRET AND EXECUTE JMP SW16B ;ONE SWEET16 INSTR. SW16C INC R15L BNE SW16D ;INCR SWEET16 PC FOR FETCH INC R15H SW16D LDA >SET ;COMMON HIGH BYTE FOR ALL ROUTINES PHA ;PUSH ON STACK FOR RTS LDY $0 LDA (R15L),Y ;FETCH INSTR AND $F ;MASK REG SPECIFICATION ASL ;DOUBLE FOR TWO BYTE REGISTERS TAX ;TO X REG FOR INDEXING LSR EOR (R15L),Y ;NOW HAVE OPCODE BEQ TOBR ;IF ZERO THEN NON-REG OP STX R14H ;INDICATE "PRIOR RESULT REG" LSR LSR ;OPCODE*2 TO LSB'S LSR TAY ;TO Y REG FOR INDEXING LDA OPTBL-2,Y ;LOW ORDER ADR BYTE PHA ;ONTO STACK RTS ;GOTO REG-OP ROUTINE TOBR INC R15L BNE TOBR2 ;INCR PC INC R15H TOBR2 LDA BRTBL,X ;LOW ORDER ADR BYTE PHA ;ONTO STACK FOR NON-REG OP LDA R14H ;"PRIOR RESULT REG" INDEX LSR ;PREPARE CARRY FOR BC, BNC. RTS ;GOTO NON-REG OP ROUTINE RTNZ PLA ;POP RETURN ADDRESS PLA JSR RESTORE ;RESTORE 6502 REG CONTENTS JMP (R15L) ;RETURN TO 6502 CODE VIA PC SETZ LDA (R15L),Y ;HIGH ORDER BYTE OF CONSTANT STA R0H,X DEY LDA (R15L),Y ;LOW ORDER BYTE OF CONSTANT STA R0L,X TYA ;Y REG CONTAINS 1 SEC ADC R15L ;ADD 2 TO PC STA R15L BCC SET2 INC R15H SET2 RTS OPTBL DFB SET-1 ;1X BRTBL DFB RTN-1 ;0 DFB LD-1 ;2X DFB BR-1 ;1 DFB ST-1 ;3X DFB BNC-1 ;2 DFB LDAT-1 ;4X DFB BC-1 ;3 DFB STAT-1 ;5X DFB BP-1 ;4 DFB LDDAT-1 ;6X DFB BM-1 ;5 DFB STDAT-1 ;7X DFB BZ-1 ;6 DFB POP-1 ;8X DFB BNZ-1 ;7 DFB STPAT-1 ;9X DFB BM1-1 ;8 DFB ADD-1 ;AX DFB BNM1-1 ;9 DFB SUB-1 ;BX DFB BK-1 ;A DFB POPD-1 ;CX DFB RS-1 ;B DFB CPR-1 ;DX DFB BS-1 ;C DFB INR-1 ;EX DFB NUL-1 ;D DFB DCR-1 ;FX DFB NUL-1 ;E DFB NUL-1 ;UNUSED DFB NUL-1 ;F * FOLLOWING CODE MUST BE * CONTAINED ON A SINGLE PAGE! SET BPL SETZ ;ALWAYS TAKEN LD LDA R0L,X BK EQU *-1 STA R0L LDA R0H,X ;MOVE RX TO R0 STA R0H RTS ST LDA R0L STA R0L,X ;MOVE R0 TO RX LDA R0H STA R0H,X RTS STAT LDA R0L STAT2 STA (R0L,X) ;STORE BYTE INDIRECT LDY $0 STAT3 STY R14H ;INDICATE R0 IS RESULT NEG INR INC R0L,X BNE INR2 ;INCR RX INC R0H,X INR2 RTS LDAT LDA (R0L,X) ;LOAD INDIRECT (RX) STA R0L ;TO R0 LDY $0 STY R0H ;ZERO HIGH ORDER R0 BYTE BEQ STAT3 ;ALWAYS TAKEN POP LDY $0 ;HIGH ORDER BYTE = 0 BEQ POP2 ;ALWAYS TAKEN POPD JSR DCR ;DECR RX LDA (R0L,X) ;POP HIGH ORDER BYTE @RX TAY ;SAVE IN Y REG POP2 JSR DCR ;DECR RX LDA (R0L,X) ;LOW ORDER BYTE STA R0L ;TO R0 STY R0H POP3 LDY $0 ;INDICATE R0 AS LAST RESULT REG STY R14H RTS LDDAT JSR LDAT ;LOW ORDER BYTE TO R0, INCR RX LDA (R0L,X) ;HIGH ORDER BYTE TO R0 STA R0H JMP INR ;INCR RX STDAT JSR STAT ;STORE INDIRECT LOW ORDER LDA R0H ;BYTE AND INCR RX. THEN STA (R0L,X) ;STORE HIGH ORDER BYTE. JMP INR ;INCR RX AND RETURN STPAT JSR DCR ;DECR RX LDA R0L STA (R0L,X) ;STORE R0 LOW BYTE @RX JMP POP3 ;INDICATE R0 AS LAST RESULT REG DCR LDA R0L,X BNE DCR2 ;DECR RX DEC R0H,X DCR2 DEC R0L,X RTS SUB LDY $0 ;RESULT TO R0 CPR SEC ;NOTE Y REG = 13*2 FOR CPR LDA R0L SBC R0L,X STA R0L,Y ;R0-RX TO RY LDA R0H SBC R0H,X SUB2 STA R0H,Y TYA ;LAST RESULT REG*2 ADC $0 ;CARRY TO LSB STA R14H RTS ADD LDA R0L ADC R0L,X STA R0L ;R0+RX TO R0 LDA R0H ADC R0H,X LDY $0 ;R0 FOR RESULT BEQ SUB2 ;FINISH ADD BS LDA R15L ;NOTE X REG IS 12*2! JSR STAT2 ;PUSH LOW PC BYTE VIA R12 LDA R15H JSR STAT2 ;PUSH HIGH ORDER PC BYTE BR CLC BNC BCS BNC2 ;NO CARRY TEST BR1 LDA (R15L),Y ;DISPLACEMENT BYTE BPL BR2 DEY BR2 ADC R15L ;ADD TO PC STA R15L TYA ADC R15H STA R15H BNC2 RTS BC BCS BR RTS BP ASL ;DOUBLE RESULT-REG INDEX TAX ;TO X REG FOR INDEXING LDA R0H,X ;TEST FOR PLUS BPL BR1 ;BRANCH IF SO RTS BM ASL ;DOUBLE RESULT-REG INDEX TAX LDA R0H,X ;TEST FOR MINUS BMI BR1 RTS BZ ASL ;DOUBLE RESULT-REG INDEX TAX LDA R0L,X ;TEST FOR ZERO ORA R0H,X ;(BOTH BYTES) BEQ BR1 ;BRANCH IF SO RTS BNZ ASL ;DOUBLE RESULT-REG INDEX TAX LDA R0L,X ;TEST FOR NON-ZERO ORA R0H,X ;(BOTH BYTES) BNE BR1 ;BRANCH IF SO RTS BM1 ASL ;DOUBLE RESULT-REG INDEX TAX LDA R0L,X ;CHECK BOTH BYTES AND R0H,X ;FOR $FF (MINUS 1) EOR $FF BEQ BR1 ;BRANCH IF SO RTS BNM1 ASL ;DOUBLE RESULT-REG INDEX TAX LDA R0L,X AND R0H,X ;CHECK BOTH BYTES FOR NO $FF EOR $FF BNE BR1 ;BRANCH IF NOT MINUS 1 NUL RTS RS LDX $18 ;12*2 FOR R12 AS STACK POINTER JSR DCR ;DECR STACK POINTER LDA (R0L,X) ;POP HIGH RETURN ADDRESS TO PC STA R15H JSR DCR ;SAME FOR LOW ORDER BYTE LDA (R0L,X) STA R15L RTS RTN JMP RTNZ -- W. Sheldon Simms | Newt's Friend / Jack Kemp for President sheldon@netcom.com | Freedom implies responsibility -------------------------+-------------------------------------------- Article 1685 of comp.sys.apple2.programmer: Newsgroups: comp.sys.apple2.programmer Path: amdahl.uts.amdahl.com!amdahl!amd!decwrl!sdd.hp.com!elroy.jpl.nasa.gov!swrinde!ihnp4.ucsd.edu!library.ucla.edu!csulb.edu!csus.edu!netcom.com!sheldon From: sheldon@netcom.com (Sheldon Simms) Subject: Sweet 16 description Message-ID: <sheldonCLz3tB.8C4@netcom.com> Organization: NETCOM On-line Communication Services (408 241-9760 guest) Date: Tue, 1 Mar 1994 06:39:11 GMT Lines: 992 Well since I posted the source, here's what it does for anyone who might not know... -Sheldon

Sweet 16 - Introduction

Integer Basic Program Machine Language Subroutine SWEET 16 Subroutine

Line 1: The first 8 bytes of data starting at $800, which is the fixed source data to be moved (in this case, the string A$).

Line 2: The first 8 bytes of data starting at the hex address entered as the destination of the move (high order byte only).

Line 3: The first 8 bytes of data starting at $0000 (the first four SWEET 16 registers).

R0 $0000 & 0001 -SWEET 16 accumulator R1 $0002 & 0003 -Source address R2 $0004 & 0005 -Destination address R3 $0006 & 0007 -Number of bytes to move . . . R14 $001C & 001D -Prior result register R15 $001E & 001F -SWEET 16 Program counter

Enter "RUN" and hit RETURN Enter "12" and hit RETURN (A$ - A$ string data) Enter "18" and hit RETURN (high-order byte of destination)

$0800-C1 40 00 10 08 B1 B2 1E (SOURCE) $0A00-C1 40 00 10 08 B1 B2 1E (Dest.) $0000-1E 00 08 08 08 0A 00 00 (SWEET 16)

A Token$ C1 40 00 10 08 B1 B2 1E --------- ---- -------- --------- -- | | | | | String VN DSP NVA DATA DATA Terminator

low high low high low high low high $0000 1E 00 08 08 08 0A 00 00 ---------- ---------- ---------- ---------- | | | | register register register register R0 R1 R2 R3 (acc) (source) (dest) (#bytes)

>List 10 PRINT "[D]BLOAD SWEET": REM CTRL D 20 CALL - 936: DIM A $ (10) 30 INPUT "ENTER STRING A $ " , A $ 40 INPUT "ENTER # BYTES " , B 50 IF NOT B THEN 40 : REM AT LEAST 1 60 POKE 778 , B : REM POKE LENGTH 70 INPUT "ENTER DESTINATION " , A 80 IF A > PEEK (203) - 1 THEN 70 90 IF A < PEEK (205) + 1 THEN 70 100 POKE 776 , A : REM POKE DESTINATION 110 M = 8 : GOSUB 160 : REM DISPLAY 120 CALL 768 : REM GOTO $0300 130 M = A : GOSUB 160 : REM DISPLAY 140 M = O : GOSUB 160 : REM DISPLAY 150 PRINT : PRINT : GOTO 30 160 POKE 60 , 0 : POKE 61 , M 170 CALL -605 : RETURN : REM XAM8 IN MONITOR Listing #2 300:20 89 F6 11 00 08 12 00 00 13 00 00 41 52 F3 07 FB 00 60 Listing #3 SWEET 16 $300 20 89 F6 JSR $F689 $303 11 00 08 SET R1 source address $306 12 00 00 SET R2 destination address A $309 13 00 00 SET R3 length B $30C 41 LD @R1 $30D 52 ST @R2 $30E F3 DCR R3 $30F 07 BNZ $30C $311 00 RTN $312 60 RTS Data will be poked from the Integer Basic program: "A" from Line 100 "B" from Line 60

SWEET 16: A Pseudo 16 Bit Microprocessor

300 B9 00 02 LDA IN,Y ;get a char 303 C9 CD CMP #"M" ;"M" for move 305 D0 09 BNE NOMOVE ;No. Skip move 307 20 89 F6 JSR SW16 ;Yes, call SWEET 16 30A 41 MLOOP LD @R1 ;R1 holds source 30B 52 ST @R2 ;R2 holds dest. addr. 30C F3 DCR R3 ;Decr. length 30D 07 FB BNZ MLOOP ;Loop until done 30F 00 RTN ;Return to 6502 mode. 310 C9 C5 NOMOVE CMP #"E" ;"E" char? 312 D0 13 BEQ EXIT ;Yes, exit 314 C8 INY ;No, cont.

NonZero

SWEET 16 Opcode Summary:

1n SET Rn Constant (Set) 2n LD Rn (Load) 3n ST Rn (Store) 4n LD @Rn (Load Indirect) 5n ST @Rn (Store Indirect) 6n LDD @Rn (Load Double Indirect) 7n STD @Rn (Store Double Indirect) 8n POP @Rn (Pop Indirect) 9n STP @Rn (Store POP Indirect) An ADD Rn (Add) Bn SUB Rn (Sub) Cn POPD @Rn (Pop Double Indirect) Dn CPR Rn (Compare) En INR Rn (Increment) Fn DCR Rn (Decrement)

00 RTN (Return to 6502 mode) 01 BR ea (Branch always) 02 BNC ea (Branch if No Carry) 03 BC ea (Branch if Carry) 04 BP ea (Branch if Plus) 05 BM ea (Branch if Minus) 06 BZ ea (Branch if Zero) 07 BNZ ea (Branch if NonZero) 08 BM1 ea (Branch if Minus 1) 09 BNM1 ea (Branch if Not Minus 1) 0A BK (Break) 0B RS (Return from Subroutine) 0C BS ea (Branch to Subroutine) 0D (Unassigned) 0E (Unassigned) 0F (Unassigned)

15 34 A0 SET R5 $A034 ;R5 now contains $A034

15 34 A0 SET R5 $A034 25 LD R5 ;ACC now contains $A034

25 LD R5 ;Copy the contents 36 ST R6 ;of R5 to R6

15 34 A0 SET R5 $A034 45 LD @R5 ;ACC is loaded from memory ;location $A034 ;R5 is incr to $A035

15 34 A0 SET R5 $A034 ;Load pointers R5, R6 with 16 22 90 SET R6 $9022 ;$A034 and $9022 45 LD @R5 ;Move byte from $A034 to $9022 56 ST @R6 ;Both ptrs are incremented

15 34 A0 SET R5 $A034 ;The low-order ACC byte is loaded 65 LDD @R6 ;from $A034, high-order from ;$A035, R5 is incr to $A036

15 34 A0 SET R5 $A034 ;Load pointers R5, R6 16 22 90 SET R6 $9022 ;with $A034 and $9022 65 LDD @R5 ;Move double byte from 76 STD @R6 ;$A034-35 to $9022-23. ;Both pointers incremented by 2.

15 34 A0 SET R5 $A034 ;Init stack pointer 10 04 00 SET R0 4 ;Load 4 into ACC 55 ST @R5 ;Push 4 onto stack 10 05 00 SET R0 5 ;Load 5 into ACC 55 ST @R5 ;Push 5 onto stack 10 06 00 SET R0 6 ;Load 6 into ACC 55 ST @R5 ;Push 6 onto stack 85 POP @R5 ;Pop 6 off stack into ACC 85 POP @R5 ;Pop 5 off stack 85 POP @R5 ;Pop 4 off stack

14 34 A0 SET R4 $A034 ;Init pointers 15 22 90 SET R5 $9022 84 POP @R4 ;Move byte from 95 STP @R5 ;$A033 to $9021 84 POP @R4 ;Move byte from 95 STP @R5 ;$A032 to $9020

10 34 76 SET R0 $7634 ;Init R0 (ACC) and R1 11 27 42 SET R1 $4227 A1 ADD R1 ;Add R1 (sum=B85B, C clear) A0 ADD R0 ;Double ACC (R0) to $70B6 ;with carry set.

10 34 76 SET R0 $7634 ;Init R0 (ACC) 11 27 42 SET R1 $4227 ;and R1 B1 SUB R1 ;subtract R1 ;(diff=$340D with c set) B0 SUB R0 ;clears ACC. (R0)

15 34 A0 SET R5 $A034 ;Init stack pointer 10 12 AA SET R0 $AA12 ;Load $AA12 into ACC 75 STD @R5 ;Push $AA12 onto stack 10 34 BB SET R0 $BB34 ;Load $BB34 into ACC 75 STD @R5 ;Push $BB34 onto stack C5 POPD @R5 ;Pop $BB34 off stack C5 POPD @R5 ;Pop $AA12 off stack

15 34 A0 SET R5 $A034 ;Pointer to memory 16 BF A0 SET R6 $A0BF ;Limit address B0 LOOP1 SUB R0 ;Zero data 75 STD @R5 ;clear 2 locations ;increment R5 by 2 25 LD R5 ;Compare pointer R5 D6 CPR R6 ;to limit R6 02 FA BNC LOOP1 ;loop if C clear

15 34 A0 SET R5 $A034 ;(Pointer) B0 SUB R0 ;Zero to R0 55 ST @R5 ;Clr Location $A034 E5 INR R5 ;Incr R5 to $A036 55 ST @R5 ;Clrs location $A036 ;(not $A035)

15 34 A0 SET R5 $A034 ;Init pointer 14 09 00 SET R4 9 ;Init counter B0 SUB R0 ;Zero ACC 55 LOOP2 ST @R5 ;Clear a mem byte F4 DCR R4 ;Decrement count 07 FC BNZ LOOP2 ;Loop until Zero

d = $80 ea = PC + 2 - 128 d = $81 ea = PC + 2 - 127 d = $FF ea = PC + 2 - 1 d = $00 ea = PC + 2 + 0 d = $01 ea = PC + 2 + 1 d = $7E ea = PC + 2 + 126 d = $7F ea = PC + 2 + 127

$300: 01 50 BR $352

15 34 A0 SET R5 $A034 ;Init pointer 14 3F A0 SET R4 $A03F ;Init limit B0 LOOP3 SUB R0 55 ST @R5 ;Clear mem byte ;Increment R5 24 LD R4 ;Compare limit D5 CPR R5 ;to pointer 04 FA BP LOOP3 ;Loop until done

15 34 A0 SET R5 $A034 ;Init pointer 1 14 3B A0 SET R4 $A03B ;Init limit 1 16 00 30 SET R6 $3000 ;Init pointer 2 0C 15 BS MOVE ;Call move subroutine 45 MOVE LD @R5 ;Move one 56 ST @R6 ;byte 24 LD R4 D5 CPR R5 ;Test if done 04 FA BP MOVE 0B RS ;Return

When is an RTS really a JSR?

LDA #ADRH ;High-order byte. STA IND+1 LDA OPTBL,X ;Low-order byte. STA IND JMP (IND)

00 1 Return to 6502 mode 01 2 Branch Always 02 2 Branch no Carry 03 2 Branch on Carry 04 2 Branch on Positive 05 2 Branch on Negative 06 2 Branch if equal 07 2 Branch not equal 08 2 Branch on negative 1 09 2 Branch not negative 1 0A 1 Break to Monitor 0B-0F 1 No operation 1R 3 R<-2 byte constant (load register immediate) 2R 1 ACC<-R 3R 1 ACC->R 4R 1 ACC<-@R, R<-R+1 5R 1 ACC->@R, R<-R+1 6R 1 ACC<-@R double 7R 1 ACC->@R double 8R 1 R<-R-1, ACC<-@R (pop) 9R 1 R<-R-1, ACC->@R AR 1 ACC<-@R(pop) double BR 1 compare ACC to R CR 1 ACC<-ACC+R DR 1 ACC<-ACC-R ER 1 R<-R+1 FR 1 R<-R-1

All braches are followed by a 1 byte relative displacement. Works identically to 6502 branches. Only ADD,SUB, and COMPARE can set carry Notation: R = a 16 bit "Register" operand designation, one of 16 labelled 0 to 15 (decimal), 0 to F (hexidecimal)

ACC = register operand R0

@R = indicrect reference, using the register R as the pointer

= assignment of values Length of instructions: Branches are always two bytes: opcodes followed by relative displacement. Load register immediate (1R) is three bytes: the hexadecimal opcode 10 to 1F followed by the 2 byte literal value of a 16 bit number. All other instructions are one byte in length.

SWEET-16 REGISTERS Register 6502 Address Purpose 0 $00,01 Accumulator 1 $02,03 General 2 $04,05 General . . . . . . . . . 11 $16,17 General 12 $18,19 Subroutine Stack Pointer 13 $1A,1B Difference of comparands 14 $1C,1D Status 15 $1E,1F Program address

SWEET-16 OPCODES

00 RTN Return to 6502 code. 0l ea BR addr Unconditional Branch. 02 ea BNC addr Branch if Carry=0. 03 ea BC addr Branch if Carry=1. 04 ea BP addr Branch if last result positive. 0S ea BM addr Branch if last result negative. 06 ea BZ addr Branch if last result zero. 07 ea BNZ addr Branch if last result non-zero. 08 ea BM1 addr Branch if last result = -1. 09 ea BNM1 addr Branch if last result not -1. 0A BK Execute 6502 BRK instruction. 0B RS Return from SWEET-16 subroutine. 0C ea BS addr Call SWEET-16 subroutine.

1n lo hi SET n,value Rn <-- value. 2n LD n R0 <-- (Rn). 3n ST n Rn <-- (R0). 4n LD @n MA = (Rn), ROL <-- (MA), Rn <-- MA+1, R0H <-- 0. 5n ST @n MA = (Rn), MA <-- (R0L), Rn <-- MA+1. 6n LDD @n MA = (Rn), R0 <-- (MA, MA+1), Rn <-- MA+2. 7n STD @n MA = (Rn), MA,MA+l <-- (R0), Rn <-- MA+2. 8n POP @n MA = (Rn)-1, R0L <-- (MA), R0H <-- 0, Rn <-- MA. 9n STP @n MA <-- (Rn)-1, (MA) <-- R0L, Rn <-- MA. An ADD n R0 <-- (R0) + (Rn). Bn SUB n R0 <-- (R0) - (Rn). Cn POPD @n MA = (Rn)-2, MA,MA+l <-- R0, Rn <-- MA. Dn CPR n R13 <-- (R0) - (Rn), R14 <-- status flags. En INR n Rn <-- (Rn) + 1. Fn DCR n Rn <-- (Rn) - 1.

1000 *------------------------------------- 1010 * CLEAR A BLOCK OF MEMORY 1020 *------------------------------------- F689- 1030 SWEET.16 .EQ $F689 0A00- 1040 BLOCK .EQ $A00 0234- 1050 N .EQ $234 1060 *------------------------------------- 0800- 20 89 F6 1070 CLEAR JSR SWEET.16 0803- 10 00 00 1080 SET 0,0 0 FOR CLEARING WITH 0806- 11 00 0A 1090 SET 1,BLOCK ADDRESS OF BLOCK 0809- 12 34 02 1100 SET 2,N # BYTES TO CLEAR 080C- 51 1110 .1 ST @1 STORE IN BLOCK 080D- F2 1120 DCR 2 080E- 07 FC 1130 BNZ .1 NOT FINISHED YET 0810- 00 1140 RTN SYMBOL TABLE 0A00- BLOCK 0800- CLEAR .1=080C 0234- N F689- SWEET.16 0000 ERRORS IN ASSEMBLY 1000 *---------------------------- 1010 * MOVE A BLOCK OF MEMORY 1020 *---------------------------- F689- 1030 SWEET.16 .EQ $F689 0A00- 1040 SOURCE .EQ $A00 0A80- 1050 DESTIN .EQ $A80 0023- 1060 N .EQ $23 1070 *---------------------------- 0800- 20 89 F6 1080 MOVE JSR SWEET.16 0803- 11 00 0A 1090 SET 1,SOURCE ADDRESS OF SOURCE BLOCK 0806- 12 80 0A 1100 SET 2,DESTIN ADDRESS OF DESTINATION BLOCK 0809- 13 23 00 1110 SET 3,N # BYTES TO MOVE 080C- 41 1120 .1 LD @1 GET BYTE FROM SOURCE 080D- 52 1130 ST @2 STORE IN DESTINATION 080E- F3 1140 DCR 3 080F- 07 FB 1150 BNZ .1 NOT FINISHED YET 0811- 00 1160 RTN SYMBOL TABLE 0A80- DESTIN 0800- MOVE .01=08CC 0023- N 0A00- SOURCE F689- SWEET.16 0000 ERRORS IN ASSEMBLY 1000 *------------------------------- 1010 * RENUMBER S-C ASSEMBLER SOURCE CODE 1020 *------------------------------- F689- 1030 SWEET.16 .EQ $F689 004C- 1040 HIMEM .EQ $4C,4D 00CA- 1050 PP .EQ $CA,CB 1060 *------------------------------- 1070 RENUMBER 0800- 20 89 F6 1080 JSR SWEET.16 0803- 11 CA 00 1090 SET 1,PP PP HAS ADDRESS OF SOURCE CODE 0806- 61 1100 LDD @1 GET ADDRESS OF SOURCE CODE 0807- 31 1110 ST 1 ...IN R1 0808- 12 0A 00 1120 SET 2,10 INCREMENT = 10 080B- 13 4C 00 1130 SET 3,HIMEM HIMEM HAS ADDR OF END OF SOURCE 080E- 63 1140 LDD @3 GET ADDRESS IN HIMEM 080F- 33 1150 ST 3 ...IN R3 0810- 14 DE 03 1160 SET 4,990 START=990 (1ST LINE WILL BE 1000) 0813- 21 1170 .1 LD 1 TEST IF FINISHED 0814- D3 1180 CPR 3 0815- 03 0E 1190 BC .2 YES 0817- 41 1200 LD @1 GET # BYTES IN THIS SOURCE LINE 0818- 35 1210 ST 5 ... INTO R5 0819- 24 1220 LD 4 GET SEQUENCE NUMBER 081A- A2 1230 ADD 2 ADD INCREMENT 081B- 34 1240 ST 4 ... INTO R4 AGAIN 081C- 71 1250 STD @1 ... AND ALSO INTO SOURCE LINE 081D- F1 1260 DCR 1 BACK UP POINTER 081E- F1 1270 DCR 1 081F- F1 1280 DCR 1 0820- 21 1290 LD 1 ADD LENGTH OF LINE TO POINTER 0821- A5 1300 ADD 5 0822- 31 1310 ST 1 POINT AT NEXT SOURCE LINE 0823- 01 EE 1320 BR .1 0825- 00 1330 .2 RTN 0826- 60 1340 RTS SYMBOL TABLE 004C- HIHEM 00CA- PP 0800- RENUMBER .01-0813, .02-0825 F689- SWEET.16 0000 ERRORS IN ASSEMBLY