在 Manus 中运行任何 Skill
一键导入
一键导入
一键在 Manus 中运行任何 Skill
开始使用$pwd:
asm6502-coder
// Write 6502/65C02 assembly code using 64tass syntax, for use within Prog8 programs
$ git log --oneline --stat
stars:196
forks:26
updated:2026年5月15日 15:45
SKILL.md
// Write 6502/65C02 assembly code using 64tass syntax, for use within Prog8 programs
| name | asm6502-coder |
| description | Write 6502/65C02 assembly code using 64tass syntax, for use within Prog8 programs |
| license | MIT |
| compatibility | opencode |
You are writing 6502/65C02 assembly using 64tass syntax, in separate *.asm files or embedded in a Prog8 program (inside %asm {{ }} blocks or asmsub routines). Follow all rules below.
*.asm (assembly source) and (with -asmlist option) also *.list (full listing with address/symbols) when compiling. Inspect these to debug generated code, verify optimizations, and trace instruction sequences..proc / .pend for procedures (scoping)_label for local labels (prefixed with underscore, scoped to .proc)+ (forward) or - (backward) at the start of a line. Reference them in branches using +, ++, +++ etc. (first/second/third upcoming anonymous forward label) and -, --, --- etc. (first/second/third preceding anonymous backward label).
+ refers to the NEXT upcoming + label, ++ refers to the ONE AFTER that, etc.- refers to the MOST RECENT - label, -- to the one before that, etc.+ label is passed, the forward-reference count resets (so ++ then refers to the next one after that new label)- dex ; backward label '-'
bne - ; branch to most recent '-' (the dex above)
ldx #5
+ dex ; forward label '+'
bne + ; branch to this same '+' (forward)
sta $400
+ lda #0 ; second '+'
bne ++ ; branch to the '++' below
rts
++ inc $d020 ; third forward label
.byte, .word, .dwordlabel = value (not label .equ value or #define)=.text for inline string datarol, ror, asl, lsr, php, pla require an explicit operand for accumulator: write rol a, ror a, not just rol/ror#), zero-page (zp), zero-page,X (zp,x), absolute (abs), absolute,X (abs,x), absolute,Y (abs,y), indirect ((abs)), indirect,X ((zp,x)), indirect,Y ((zp),y), relative (branches), accumulatorbne, beq, bmi, bpl, bcs, bcc, bvs, bvc (relative, max +127/-128 bytes)jmp (absolute or indirect), jsr/rts (subroutine call/return)push/pop mnemonics — use pha/pla (byte) and txa/phx/plx/tay/phy/ply for registersstz, phx, plx, phy, ply, bra, trb, tsb, stp, wai, clr, ina, dea, cmp (zp), dec/inc abs,x etc.stz, no phx/plx/phy/ply, no braclobbers (A, X, Y) when writing asmsub%asm {{ }} blocksasmsub (assembly subroutine)@A, @X, @Y, @AX (A low, X high), @AY (A low, Y high), @R0-@R15, @FAC1/@FAC2 (float), @Pc (carry), @Pz (zero)-> type @register — also via @Pz/@Pc for flagsclobbers (A, X, Y) — MUST list all modified registersx1 = cx16.r0, y1 = cx16.r0LExample:
asmsub line(uword x1 @R0, ubyte y1 @A, uword x2 @R1, ubyte y2 @Y) clobbers (A, X, Y) {
%asm {{
x1 = cx16.r0
x2 = cx16.r1
lda x1 ; use alias, not "_x1"
}}
}
asmsub parameter annotation reference| Annotation | Register | Size |
|---|---|---|
@A | Accumulator | 8-bit |
@X | X register | 8-bit |
@Y | Y register | 8-bit |
@AX | A (low) + X (high) | 16-bit |
@AY | A (low) + Y (high) | 16-bit |
@R0-@R15 | cx16 virtual registers | 16-bit each |
@FAC1/@FAC2 | Floating-point accumulators | 5-byte float |
@Pc | Carry flag | bool |
@Pz | Zero flag | bool |
All Prog8 symbols are prefixed when accessed from assembly:
| Prefix | Refers to | Example |
|---|---|---|
p8v_ | Variables, parameters | p8v_myvar |
p8s_ | Subroutines | p8s_mysub |
p8b_ | Blocks | p8b_myblock |
p8c_ | Constants, enum members | p8c_myconst, p8c_MyEnum_Member |
p8l_ | Labels | p8l_mylabel |
p8t_ | Struct types | p8t_MyStruct |
p8_ | Other symbols |
p8b_myblock.p8v_myvar, p8b_myblock.p8s_mysub.p8v_localvar.proc (subroutine) in your assembly, short names often work (assembler scoping)%option no_symbol_prefixing: disables all prefixes. Stdlib modules (cbm, cx16, txt) use this — you can write cbm.CHROUT directly_lsb and _msb to the name: p8v_myarray_lsb, p8v_myarray_msbP8ZP_SCRATCH_B1 (byte)P8ZP_SCRATCH_REG (byte)P8ZP_SCRATCH_W1 (word)P8ZP_SCRATCH_W2 (word)P8ZP_SCRATCH_PTR (word)cx16.r0-cx16.r15 are in zeropage (and their low/high bytes: cx16.r0L, cx16.r0H, etc.)cx16.r0-cx16.r15 are available on ALL targets, but only on CX16 in zeropage ldx #count
loop ; do work here
dex
bne loop ; loop while X != 0
ldy #index
lda (ptr),y ; read byte at address stored in zp ptr + Y
clc
lda word1_lo
adc word2_lo
sta result_lo
lda word1_hi
adc word2_hi
sta result_hi
jsr p8s_myblock.p8s_mysub
lda p8v_myword ; loads LSB
ldy p8v_myword+1 ; loads MSB (word variables are stored LSB-first)