CS 562: Project 1 Preliminary


This project is meant to get you started working with the 6502, especially with writing high-level (C) code for it and writing 6502 assembly. Having this understanding will help when you're building and debugging your own 6502 emulator. Before you get started with the project, you will want to familiarize yourself with the 6502 instruction set, e.g. by looking here. You can get used to writing and assembling 6502 programs here. There are plenty of other references and tutorials elsewhere online.

Part 1: Getting Started

On a Linux system of your choosing (e.g. a Linux VM), first download the cc65 toolchain. This is a set of cross-compiler tools for compiling from C to 6502 ASM targeting various platforms. It also includes a 6502 simulator, which we'll be using for this project (since we don't have our own emulator yet!). First, get the codebase by running the following:

    $> git clone https://github.com/cc65/cc65.git
    $> cd cc65
    $> make
If you have admin access on your system (recommended, use a VM if you must), you can make it such that the binaries are globally available by running the following:
    $> sudo make avail

Now let's build a simple Hello World program that we can run on the provided 6502 simulator. Note that for this example I'm assuming that you are in the cc65 directory.

    $> cat test.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>

    int main () { printf("Hello World\n"); }

We then need to cross-compile this code for the 6502. Note that when we say cross-compile, we mean that we're compiling on one platform for another platform. We typically use cross compilers when building OSes or programs for embedded systems or systems which are not capable of hosting their own compiler.

First, we compile from C to 6502 assembly:

    $> cc65 -t sim6502 -o test.s test.c

This invokes the 6502 C compiler, and we tell it with the -t flag that we're compiling for the simulator platform. Note that cc65 also has other targets like the NES and Commodore 64. The result is that we have a file containing the 6502 assembly language for our Hello World program (test.s), which we must now assemble into an object file that can be linked:

    $> ca65 test.s

This invokes the 6502 assembler, which assembles the program and produces an object file named test.o, which we can now link:

    $> ld65 -t sim6502 -o test test.o lib/sim6502.lib

Notice here that when we invoke the 6502 linker, we again specify the target simulator platform, but we also link with a library. This is a pre-built library included in cc65 which gives us most of the C standard library (e.g. printf) for the simulated platform. The result is that we now have a binary executable for the simulator that we can now run:

    $> sim65 test
    Hello World

We can save some time by invoking cc65's compiler wrapper, which will do the above three steps for us (compile, assemble, and link):

    $> cl65 -t sim6502 test.c
    $> sim65 test
    Hello World

Part 2: Fibonacci

Your goal here is to write a program that calculates the nth Fibonacci number and outputs the result to the simulator console. You will do this in two ways. The first will purely be in C. So that we don't have to deal with input devices, you should define N as a preprocessor macro, i.e.:

    #define N 10
In your first implementation, you should only have one C file which contains two functions, main() and fib(int n).

For your second implementation, you will implement fibas a 6502 assembly routine in a separate file called fib.s. You will want to make use of the ca65 User's Guide, the 6502 Instruction Set Reference, and perhaps some code samples to write your program.

When you're done, you should have two files, fib.s, main.c. You can produce object files using cc65 and ca65 as above and then link all the object files together (along with sim6502.lib) to produce a binary that you can run on the 6502 simulator. Your program should print only the result of the computation, e.g. if N is defined as 25:

    $> sim65 fib
Note that you perform output in C. Your assembly should only include the implementation of fib (unless you really want to write it all in assembly).