Free NES assembler

0. Contents

   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.7. Command separation
      3.8. Code pointer relocation
      3.9. Branch labels
      3.10. Preprocessor
      3.11. Object file format
      3.12. IPS output support
      3.13. Linkage selection
   4. Changelog
   5. Known bugs
   6. Copying
   7. Requirements
   8. Downloading

1. Purpose

This program reads symbolic 6502/RP2A03/RP2A07 machine code and compiles (assembles) it into a relocatable object file or into an IPS patch.

The produced object file is binary-compatible with those made with XA65.

1.1. History

This program was born when Bisqwit needed to have something for NES that is already accomplished for SNES by snescom.

2. Linker

This package also contains a linker.

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: neslink input.ips -o result.bin -f raw

3. Supported syntax

3.1. Mnemonics

The following mnemonics are supported:

adc, and, asl, bcc, bcs, beq, bit, bmi, bne, bpl, brk, bvc, bvs, clc, cld, cli, clv, cmp, cpx, cpy, dec, dex, dey, eor, inc, inx, iny, jmp, jsr, lda, ldx, ldy, lsr, nop, ora, pha, php, pla, plp, rol, ror, rti, rts, sbc, sec, sed, sei, sta, stx, sty, tax, tay, tsx, txa, txs, tya

3.2. Addressing modes

All the standard addressing modes of the 6502 cpu are supported.

Name Examples Functionally equivalent to (not nescom syntax, provided for illustration only)
Implied: nop; clc
Immediate: lda #value etc a = value
Short relative: bcc end
Direct: lda $12 a = ram[$0012]
Direct indexed: lda $12,x
lda $12,y
a = ram[$0012 + x]
a = ram[$0012 + y]
Direct indexed indirect: lda ($12,x) a = ram[ramw[$0012 + x]]
Direct indirect indexed: lda ($12),y a = ram[ramw[$0012] + y]
Absolute: lda $1234 a = ram[$1234]
Absolute indexed: lda $1234,x
lda $1234,y
a = ram[$1234 + x]
a = ram[$1234 + y]
Absolute indirect: lda ($1234) a = ram[ramw[$1234]]
Note: "ram" and "ramw" in the table refer to generic address space access (RAM, I/O ports, ROM etc). "ramw" means 16-bit read access, but the meaning of "ram" depends on the context. It can be a read, write or a jump target, depending on instruction.

3.3. Operand size control

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 #<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.

3.4. Expression evaluation

Expressions are supported. These are valid code:
  • bcc somewhere+1
  • lda #!address + $100
  • ldy #$1234 + ($6C * 3)

3.5. Segments

Code, labels and data can be generated to four segments: text, data, zero and bss.
Use .text, .data, .zero and .bss respectively to select the segment.
However, only the contents of text and data segments are saved into the o65 file. Labels are saved in all segments.


Comments begin with a semicolon (;) and end with a newline.
A colon is allowed to appear in comment.

3.7. Command separation

Commands are separated by newlines and colons (:).

3.8. Code pointer relocation

You can use a command like *= $F200 to change where the code goes by default.
With IPS this is especially useful.
You can change the code pointer as many times as you wish, but unless you're generating an IPS file, all code must be a continuous block.

3.9. Branch labels

The label - can be defined for local branches backward and + for branches forward.

3.10. Preprocessor

nescom uses GCC as a preprocessor.
You can use #ifdef, #ifndef, #define, #if, #endif and #include like in any C program. (See bugs)

3.11. Object file format

nescom produces relocatable object files (O65), non-relocatable patch files (IPS), or raw files.
The O65 file format has been documented by André Fachat for the XA65 project.

3.12. IPS output support

This version of nescom allows you to create IPS files.
This IPS format has been extended to allow you to specify global symbols and externs to be patched later.
In the generated format:
  • If the patch address is $000001, it means this entry is a dynamic symbol. What follows is an asciiz string (the symbol name), the address (3-byte lsb-first integer) and the relocation size in bytes (1 byte).
  • If the patch address is $000002, it means this entry is a global symbol. What follows is an asciiz string (the symbol name) and the address (3-byte lsb-first integer) where this symbol is located in.

3.13. Linkage selection

By default, O65 objects are linked to any free location in the ROM.
IPS files are linked to predefined locations.

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.

This is not completely ready for NES yet.

4. Changelog

Nov 20 2005; 0.0.0 import from snescom-
Nov 29 2005; 0.1.0 bugfixes, now it's functional.
Dec 16 2005; 0.2.0 support for deeper "++" and "--" labels. Also support for .nop statement.
Jun 20 2006; 1.0.0 raw output file format support in nescom. Also using boost::smart_ptr.
Jul 26 2006; 1.1.0 has now a linker, and an example program.
Jul 27 2006; 1.1.1 adds some consistency to ROM and NES address space conversions.
Sep 21 2006; 1.1.2 adds clever_disasm and some documentation changes.
Oct 9 2006; 1.1.3 fixes a crash & memory leak bug.
May 13 2007; fixes a bug regarding comments in #included files.
Oct 27 2007; 1.1.4 added some new features in clever-disasm, and example ini files.
Mar 27 2016; 1.1.8 added xa65 obj file support, and no longer depends on libboost.

5. Known bugs

  • #included files aren't being properly preprocessed.
  • memory mapping is not properly designed yet.

6. Copying

nescom has been written by Joel Yliluoma, a.k.a. Bisqwit,
and is distributed under the terms of the General Public License (GPL).

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.

7. Requirements

nescom uses GCC as a slave in the preprocessing phase. Therefore, GCC must be installed and found in the PATH when running nescom.

8. Downloading

Downloading help

  • Do not download everything - you only need one file (newest version for your platform)!
  • Do not use download accelerators or you will be banned from this server before your download is complete!

The most recent source code (bleeding edge) for nescom can also be downloaded by cloning the Git repository by:

Date (Y-md-Hi) acc        Size Name                
2016-0327-2119 r--      140764 nescom-1.1.8.tar.bz2
2016-0327-2119 r--      159195 nescom-1.1.8.tar.gz
2013-0416-1150 r--      131449 nescom-1.1.7.tar.bz2
2013-0416-1150 r--      148806 nescom-1.1.7.tar.gz
2013-0301-1705 r--      518041
2012-1022-1116 r--      112490 nescom-1.1.6.tar.bz2
2012-1022-1116 r--      128113 nescom-1.1.6.tar.gz
2011-0612-1318 r--      102111 nescom-
2011-0612-1318 r--      117217 nescom-
2010-0822-0446 r--      100672 nescom-
2010-0822-0446 r--      115795 nescom-
2009-1230-1446 r--       98730 nescom-1.1.5.tar.bz2
2009-1230-1446 r--      113933 nescom-1.1.5.tar.gz
2007-1027-2027 r--       92227 nescom-1.1.4.tar.bz2
2007-1027-2027 r--      106050 nescom-1.1.4.tar.gz
2007-1027-2027 r--       16104 patch-nescom-
2007-1027-2027 r--       17036 patch-nescom-
2007-1027-2027 r--       20951 patch-nescom-1.1.3-1.1.4.bz2
2007-1027-2027 r--       22378 patch-nescom-1.1.3-1.1.4.gz
2007-0513-0403 r--       80947 nescom-
2007-0513-0403 r--       94164 nescom-
2007-0513-0403 r--        7496 patch-nescom-1.1.3-
2007-0513-0403 r--        7636 patch-nescom-1.1.3-
2006-1009-0016 r--       79465 nescom-1.1.3.tar.bz2
2006-1009-0016 r--       92263 nescom-1.1.3.tar.gz
2006-1009-0016 r--        6757 patch-nescom-1.1.2-1.1.3.bz2
2006-1009-0016 r--        6882 patch-nescom-1.1.2-1.1.3.gz
2006-0921-0117 r--       77164 nescom-1.1.2.tar.bz2
2006-0921-0117 r--       88879 nescom-1.1.2.tar.gz
2006-0921-0117 r--       17332 patch-nescom-1.1.1-1.1.2.bz2
2006-0921-0117 r--       19219 patch-nescom-1.1.1-1.1.2.gz
2006-0727-1707 r--       63261 nescom-1.1.1.tar.bz2
2006-0727-1707 r--       72607 nescom-1.1.1.tar.gz
2006-0727-1707 r--        4927 patch-nescom-1.1.0-1.1.1.bz2
2006-0727-1707 r--        4776 patch-nescom-1.1.0-1.1.1.gz
2006-0727-1347 r--       62982 nescom-1.1.0.tar.bz2
2006-0727-1347 r--       72456 nescom-1.1.0.tar.gz
2006-0727-1347 r--       17922 patch-nescom-1.0.0-1.1.0.bz2
2006-0727-1347 r--       20336 patch-nescom-1.0.0-1.1.0.gz
2006-0620-1156 r--      142578
2006-0620-1325 r--       60392 nescom-1.0.0.tar.bz2
2006-0620-1325 r--       69370 nescom-1.0.0.tar.gz
2006-0620-1325 r--        9371 patch-nescom-0.2.0-1.0.0.bz2
2006-0620-1325 r--        9320 patch-nescom-0.2.0-1.0.0.gz
2005-1216-1353 r--       58979 nescom-0.2.0.tar.bz2
2005-1216-1353 r--       67451 nescom-0.2.0.tar.gz
2005-1216-1353 r--        5220 patch-nescom-0.1.0-0.2.0.bz2
2005-1216-1353 r--        5141 patch-nescom-0.1.0-0.2.0.gz
2005-1129-1516 r--       58289 nescom-0.1.0.tar.bz2
2005-1129-1516 r--       66322 nescom-0.1.0.tar.gz
2005-1129-1516 r--       33492 patch-nescom-0.0.0-0.1.0.bz2
2005-1129-1516 r--       35796 patch-nescom-0.0.0-0.1.0.gz
2005-1120-0021 r--       64913 nescom-0.0.0.tar.bz2
2005-1120-0021 r--       73319 nescom-0.0.0.tar.gz
Back to the source directory index at Bisqwit's homepage