Wozasm
Since reading the iWOZ book I have been getting all
of Wozniac's early asm code I can get hold of and it is all
pretty amazing!
It is in the dialect of an old 8 bit processor (6502) so you
have to get stuff like an opcode list to make any sense of it
but that is all available on the web...use google.
The code is really compact, it's good learning material for
anyone wanting to hone their asm skills.
Here is a totally awesome bit of code he wrote that creates
a software based 16 bit processor with its own opcodes.
Note how tiny this code is! code for a pseudo processor
in only 300 bytes!
Here are some notes about the pseudo processor.
There is an old book full of Wozniac's code snippets.
Nobody seems able to come up with a copy...I'd sure
like a pdf of this thing

This code was not written for something as different as the Propeller
but the ideas can really make you think. The asm is not that far removed
from something like an 8 bit AVR though.
I wish that this guy would write some PASM code
www.6502.org/tutorials/6502opcodes.html
Post Edited (HollyMinkowski) : 6/11/2010 1:49:07 PM GMT
of Wozniac's early asm code I can get hold of and it is all
pretty amazing!
It is in the dialect of an old 8 bit processor (6502) so you
have to get stuff like an opcode list to make any sense of it
but that is all available on the web...use google.
The code is really compact, it's good learning material for
anyone wanting to hone their asm skills.
Here is a totally awesome bit of code he wrote that creates
a software based 16 bit processor with its own opcodes.
Note how tiny this code is! code for a pseudo processor
in only 300 bytes!
********************************
* *
* 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
Here are some notes about the pseudo processor.
WOZ said...
SWEET 16: A Pseudo 16 Bit Microprocessor
by Steve Wozniak
Description:
While writing APPLE BASIC for a 6502 microprocessor, I repeatedly encountered a variant of MURPHY'S LAW. Briefly stated, any routine operating on 16-bit data will require at least twice the code that it should. Programs making extensive use of 16-bit pointers (such as compilers, editors, and assemblers) are included in this category. In my case, even the addition of a few double-byte instructions to the 6502 would have only slightly alleviated the problem. What I really needed was a 6502/RCA 1800 hybrid - an abundance of 16-bit registers and excellent pointer capability.
My solution was to implement a non-existant (meta) 16-bit processor in software, interpreter style, which I call SWEET 16.
SWEET 16 is based on sixteen 16-bit registers (R0-15), which are actually 32 memory locations. R0 doubles as the SWEET 16 accumulator (ACC), R15 as the program counter (PC), and R14 as the status register. R13 holds compare instruction results and R12 is the subroutine return stack pointer if SWEET 16 subroutines are used. All other SWEET 16 registers are at the user's unrestricted disposal.
SWEET 16 instructions fall into register and non-register categories. The register ops specify one of the sixteen registers to be used as either a data element or a pointer to data in memory, depending on the specific instruction. For example INR R5 uses R5 as data and ST @R7 uses R7 as a pointer to data in memory. Except for the SET instruction, register ops take one byte of code each. The non-register ops are primarily 6502 style branches with the second byte specifying a +/-127 byte displacement relative to the address of the following instruction. Providing that the prior register op result meets a specified branch condition, the displacement is added to the SWEET 16 PC, effecting a branch.
SWEET 16 is intended as a 6502 enhancement package, not a stand alone processor. A 6502 program switches to SWEET 16 mode with a subroutine call and subsequent code is interpreted as SWEET 16 instructions. The nonregister op RTN returns the user program to 6502 mode after restoring the internal register contents (A, X, Y, P, and S). The following example illustrates how to use SWEET 16.
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.
WOZ said...
SWEET16 contains sixteen internal 16 bit registers, actually the first 32 bytes in main memory, labelled R0 through R15. R0 is defined as the accumulator, R15 as the program counter, and R14 as a status register. R13 stores the result of all COMPARE operations for branch testing. The user acceses SWEET16 with a subroutine call to hexadecimal address F689. Bytes stored after the subroutine call are thereafter interpreted and executed by SWEET16. One of SWEET16's commands returns the user back to 6502 mode, even restoring the original register contents.
Implemented in only 300 bytes of code, SWEET16 has a very simple instruction set tailored to operations such as memory moves and stack manipulation. Most opcodes are only one byte long, but since she runs approximately ten times slower than equivalent 6502 code, SWEET16 should be employed only when code is at a premium or execution is not. As an example of her usefulness, I have estimated that about 1K byte could be weeded out of my 5K byte Apple-II BASIC interpreter with no observable performance degradation by selectively applying SWEET16. [noparse]/noparse
There is an old book full of Wozniac's code snippets.
Nobody seems able to come up with a copy...I'd sure
like a pdf of this thing

This code was not written for something as different as the Propeller
but the ideas can really make you think. The asm is not that far removed
from something like an 8 bit AVR though.
I wish that this guy would write some PASM code

www.6502.org/tutorials/6502opcodes.html
Post Edited (HollyMinkowski) : 6/11/2010 1:49:07 PM GMT

Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
···································Fix it, if ain't broke!
D Rat
Dave Ratcliff N6YEE
ftp://public.asimov.net/pub/apple_II/
Rich Green
I missed the elegant simplicity of the 6502 till I found the Prop.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"I mean, if I went around sayin' I was an emperor just because some moistened bint had lobbed a scimitar at me they'd put me away!"
IMHO, a card for the Apple ][noparse][[/noparse], containing a Propeller, designed for slot 7, or 0, whichever one of those lets you take over the Apple CPU, would make for a very interesting, though large, propeller dev station. Been wanting to do it actually.
The 6502 is interesting and fun today because of all the tricks possible. Over time, people have continued to make shorter and or faster code. The same is true for other CPUs too. An example of this on 6809 is moving big blocks of memory using the stack instructions. Set up an address, push a lot of RAM onto the registers, pull it back off at the new address, letting the auto increment do it's thing. Beats the heck out of a load, load, index, store, store loop.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Wondering how to set tile colors in the graphics_demo.spin?
Safety Tip: Life is as good as YOU think it is!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chris Savage
Parallax Engineering
·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The early bird gets the worm but the second mouse gets the cheese.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Searider
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Wondering how to set tile colors in the graphics_demo.spin?
Safety Tip: Life is as good as YOU think it is!
One thing they share is a dependency on self-modifying code.
I wasn't given much instruction on the 6502 before my first programming task, and I can still remember the surprise when I found, in the middle of the task, that the only way I could figure to do a particular thing was to code a jump to a dummy location and then go back and rewrite the operand field during runtime. I had never heard the expression "self-modifying code," and I was almost embarrassed about what I thought was just my crazy scheme.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The early bird gets the worm but the second mouse gets the cheese.