s502 assembler
A very simple assembler for the 6502 line of processors written in C
|
Sixty-502 assembler is a simple assembler program for the 6502 line of processors written in C.
It is also my homework project in programming on BME.
IMPORTANT
The goal of this program is to convert one or many assembly source files to machine code binary files. This is a moderately complex task, especially as we need robust error handling as there are many possible sources of failure, such as wrong filenames or invalid inputs.
The assembler consist of an executable file (asm.exe
on windows), and an instructions file (opcodes.csv
).
The former is the main executable of the program.
The later is used by the assembler to load instruction data from, and should be placed in CWD or in PATH, otherwise the assembler will not find it and fail.
The assembler can be run from the command line: asm.exe input.asm
Additional settings can also be applied:
-l <loglevel>
to set logging level -o <outputfile>
to set output file out.bin
). name
has an upper length limit set in state.h
-d <name> <value>
to define a constant. map.h
, value is non-negative decimal number). The input file should be a valid source file
The program assembles the source(s) into a binary and saves the result into the specified output file.
If the program encounters some errors, it prints it's cause and stops, de-allocating all resources it has before exiting.
Full list of errors and possible causes
The project ships with VSCode project set-up for Windows+GCC, the default build task generates asm.exe
with -O3
, -Wall
and -Werror
.
If not using VSCode or Windows, use the command:
gcc -o asm -O3 -Wall -Werror src/*.c
Two example files are provided in the root folder:
example.asm
c64.asm
c64.asm
is a "header" file not generating any binary, but defining useful labels for programming the C=64 computer
example.asm
is a demo program of the assembler for the C=64 (using c64.asm
).
For trying out the example, I recommend using a C=64 emulator such as VICE
Assemble the example with
asm.exe -o example.prg example.asm
The resulting file is a valid .prg
file that can be loaded (or just drag&dropped) in the emulator (or even a real C=64)
The demo can also be assembled with different parameters by setting these constants:
WAIT
max counter value used in the busy wait loop in the demo. Default value is 3000, setting it lower will make the demo run fasterCRAZY_EFFECT
setting it to any value will cause a crazy visual effect in the waiting screenBORDERCHANGE
setting it to any value will cause the screen border to be changed in the demoThe provided example file uses nearly all features of the assembler, including
Thus making a good cover test if everything works. Excluded from that example:
For testing the different address modes, this program covers all remaining ones:
(comments are hex values they should assemble, hand-assembled from the datasheet)
For errors, see errors list
The project code only contains C source along with header files. All of those are located in the src
directory.
The sources are split up into multiple C files with multiple headers. Headers are always named same as the corresponding sources except for token_t.h
which has no associated C source and debugmalloc.h
which is a debugging utility not written by me.
(The original debugmalloc.h
raised a assembler warning (a false positive my program also had), so I added GCC pragmas to suppress that.)
The program uses no global variables and only one static variable (global log level, accessed via logging_level()).
Objects:
Naming:
Errors:
Commenting:
There are many of them, a complete list of them and their descriptions is seen on the auto-generated pages
Compiler state, e.g constants, labels, tokens and settings.
Emulates a global object by being passed to many functions.
Key->value map for string keys and non-negative integer values.
Used for constants and labels. Backed by a singly linked list without sentinels.
Simple stack for non-negative integers.
Only used to store state of conditional compilation in step_one.c
Type that stores instruction data (mnemonic, codes of different addressing modes)
Always bound to a linked list of them
Most used data type, gathering all data about a single token
Holds source (for printing source of error), stripped text, address, binsize, instruction pointer (if instruction), operand, etc.
A doubly linked list of tokens for storing file(s) contents
Supports delete and insert operations
Some utility functions
Number parsing
Directive processing (step 1 and 3)
File loading and tokenizing
First step
Steps 2 and 3 (i.e writing output)