1. Purpose 1.1. History 2. Linker 3. Supported syntax 3.1. Mnemonics 3.2. Addressing modes 3.3. Operand size control 3.4. Expression evaluation 3.5. Segments 3.6. Comments 3.7. Command separation 3.8. Code pointer relocation |
3.9. Branch labels 3.10. Preprocessor 3.11. Object file format 3.12. Automatic jump size detection 3.13. IPS output support 3.14. Linkage selection 4. Examples and more documentation 5. Changelog 6. Known bugs 7. Copying 8. Requirements 9. Downloading |
The produced object file is binary-compatible with those made with XA65.
The linker can also be used to convert IPS patches into
binary files (an empty space is assumed to be the original
file), with the following command:
sneslink input.ips -o result.bin -f raw
adc
, and
, asl
, bcc
,
bcs
, beq
, bit
, bmi
,
bne
, bpl
, bra
, brk
,
brl
, bvc
, bvs
, clc
,
cld
, cli
, clv
, cmp
,
cop
, cpx
, cpy
, db
,
dec
, dex
, dey
, eor
,
inc
, inx
, iny
, jml
,
jmp
, jsl
, jsr
, lda
,
ldx
, ldy
, lsr
, mvn
,
mvp
, nop
, ora
, pea
,
pei
, per
, pha
, phb
,
phd
, phk
, php
, phx
,
phy
, pla
, plb
, pld
,
plp
, plx
, ply
, rep
,
rol
, ror
, rti
, rtl
,
rts
, sbc
, sec
, sed
,
sei
, sep
, sta
, stp
,
stx
, sty
, stz
, tax
,
tay
, tcd
, tcs
, tdc
,
trb
, tsb
, tsc
, tsx
,
txa
, txs
, txy
, tya
,
tyx
, wai
, xba
, xce
Syntax:
Name | Examples | Functionally equivalent to (not snescom syntax, provided for illustration only) |
---|---|---|
Implied: | nop ; clc |
|
Immediate: | lda #value ; rep #value etc (size may depend on an operand size setting) |
a = value |
Short relative: | bra end |
|
Long relative: | brl end ; per end+2 |
|
Direct: | lda $12 |
a = ram[$00 : d + $0012] |
Direct indexed: | lda $12,x lda $12,y |
a = ram[$00 : d + $0012 + x] a = ram[$00 : d + $0012 + y] |
Direct indirect: | lda ($12) ; pei ($12) |
a = ram[db: ramw[$00 : d + $0012]] |
Direct indexed indirect: | lda ($12,x) |
a = ram[db: ramw[$00 : d + $0012 + x]] |
Direct indirect indexed: | lda ($12),y |
a = ram[db: ramw[$00 : d + $0012] + y] |
Direct indirect long: | lda [$12] |
a = ram[raml[$00 : d + $0012]] |
Direct indirect indexed long: | lda [$12],y |
a = ram[raml[$00 : d + $0012] + y] |
Absolute: | lda $1234 |
a = ram[db : $1234] |
Absolute indexed: | lda $1234,x lda $1234,y |
a = ram[db : $1234 + x] a = ram[db : $1234 + y] |
Absolute long: | lda $123456 |
a = ram[$12 : $3456] |
Absolute indexed long: | lda $123456,x |
a = ram[$12 : $3456 + x] |
Stack-relative: | lda $12,s |
a = ram[$00 : $0012 + s] |
Stack-relative indirect indexed: | lda ($12,s),y |
a = ram[db : ramb[$00 : $0012 + s] + y] |
Absolute indirect: | lda ($1234) |
a = ram[db : ramw[db : $1234]] |
Absolute indirect long: | lda [$1234] |
a = ram[raml[db : $1234]] |
Absolute indexed indirect: | lda ($1234,x) |
a = ram[raml[db : $1234 + x]] |
MVN/MVP: | mvn $7E,$7F |
$00 :
) refers to the
page selection (i.e. the 8 most significant bits of the 24-bit address).
.as
, .al
, .xs
&
.xl
are used to decide what size accumulator and index mode
for the assembler to use. .as
and .xs
are for
8bit operands, and .al
and .xl
are for 16 bit operands.
I've found it handy to define these macroes:
#define SET_8_BIT_A() sep #$20 : .as #define SET_16_BIT_A() rep #$20 : .al #define SET_8_BIT_X() sep #$10 : .xs #define SET_16_BIT_X() rep #$10 : .xl #define SET_8_BIT_AX() sep #$30 : .xs : .as #define SET_16_BIT_AX() rep #$30 : .xl : .alIn addition to these modes, there are several operand prefixes that can be used to force a certain operand size/type.
lda !$f0
would use 16-bit address instead of direct page.lda @$1234
would use a long (24-bit) address instead of absolute 16-bit address.lda #<var
can be used to load the lower 8 bits of an external variable.lda #>var
can be used to load the upper 8 bits of an external variable.lda #^var
can be used to load the segment part (8 bits) of an external variable.lda @var,x
can be used to use absolute-indexed-long mode instead of the default, absolute.bra somewhere+1
lda #!address + $100
ldy #$1234 + ($6C * 3)
text
, data
, zero
and bss
..text
, .data
, .zero
and .bss
respectively to select the segment.text
and data
segments are saved into
the o65 file. Labels are saved in all segments.
*= $34F200
to change
where the code goes by default.-
can be defined for local branches
backward and +
for branches forward.; Space-fill the buffer to end phx cpx #$0010 bcs + ;jumps to the next "+" SET_8_BIT_A() lda #$FF - sta $94A0,x sta $94B0,x inx cpx #$0010 bcc - ;jumps to the previous "-" SET_16_BIT_A() + lda W_VRAMADDR sta @$002116 pla
#ifdef
, #ifndef
, #define
,
#if
, #endif
and #include
like
in any C program. (See bugs)
--jumps
option is enabled, all short
jumps are automatically turned into near jumps when
needed. (See bugs)
With the .link
statement, you can change that.
.link page $3F
declares that this object should be
placed into page $3F.
.link group 1
declares that this object should be
placed to the same page together with all other objects that
want to be linked in group 1. This is useful when you want to
ensure that certain tables or routines go to the same page,
even if they are not in the same compilation unit.
The actual page is determined during link time, and you can
get the page by using 24-bit (@) or segment reference (^)
to a symbol from those modules.
The linkage selection statement is only honored by the
sneslink
program, distributed in this archive.
sneslink has currently been tested only with HiROMs.
There's also an example program demonstrating the linker at http://bisqwit.iki.fi/src/snescom-demo/.
#include
d files aren't being properly preprocessed.--jumps
option is not failsafe - three pass
jump optimization is not supported.If you happen to see this program useful for you, I'd appreciate if you tell me :) Perhaps it would motivate me to enhance the program.
Generated from
progdesc.php (last updated: Sun, 04 Mar 2012 01:33:36 +0200)
with docmaker.php (last updated: Sun, 04 Mar 2012 01:33:36 +0200)
at Sun, 04 Mar 2012 01:33:37 +0200