March, 2020

Chicken run: an assembly project

Abstract

Meet Ghunter, the anxiety packed chicken! Years past after Ghunter lost his son to a flower allergy. His wife got into a cloud overdose not long after that... Now both the flowers and clouds have returned to finish their job on the miserable Ghunter! Try to dodge a smany pesky flowers and clouds as possible to keep Ghutner alive!

The project

In this project I learned the basics of writing assembly code and how to work with a MOS 6502 simulator. I think for me this was a most interesting topic as getting to know how everything works low level is I think one of my many interests in programming. This is why I absolutly loved working on it.

The simulator

The simulator is memory mapped:

  • Display
    • top left corner: $0200
    • nottom right corner: $05FF
  • Stack pointer
    • start: $0100
    • end: $01FF

Registers

registers image
  • A  accumulator register.
  • X,Y  index registers.
  • SP  stack pointer.
  • PC  program counter
  • P  7 processor status flag bits
    • N  negative > if bit 7 is set.
    • V  overflow > if sign bit is incorrect.
    • B  break > not affected
    • D  decimal > not affected
    • I  interrupt > not affected
    • Z  zero > set if A == 0
    • C  carry > set if overflow in bit 7

The most important flags are the zero and carry flag.

Assembly: the baby steps

The difference between #$01 and $01

If you use LDA #$10; then you will store the hexadecimal value $01 in register A. If you use LDA $01; then you will store the hexadecimal value in memory place $01 in register A.

Most used instructions

  • LDA - LDX - LDY  Load number into register A-X-Y.
  • STA  Store number in given memory address.
  • TAX - TAY  Transfer value in register A to register X-Y.
  • ADC  Add with carry to register A.
  • SBC  Substract with carry from register A.
  • INX - INY  Increment register X-Y.
  • INC  Increment value in given address.
  • DEX - DEY  Decrement register X-Y.
  • DPX - CPY - CMP  Compares register X-Y-given address with a value in a given address. This operation can se the flags N, Z and C if approopriate.

Addressing modes

There are a lot of different addressing modes. The most standard one is absolute addressing, this is when you fully give the address.
A variant on this is the zero page addressing mode, this is actually single-byte addressing. This will work faster than absolute addressing because you only have a 1 byte lookup. It will also take less space in code. The only drawback about zero page addressing is that this only work for the first 256 bytes, e.g. the first page.
When we talk about immediat addressing then we use the actual values instead of with the memory addresses.
Relative or label addressing is used mainly for branching.
With implicit addressing, you work with instructions that don't deal with memory locations but with registers, this means that the argument is implied by the instructions.
Another one is that one can use indirect addressing. This means that you use an absolute address to look up another address. The first address will then be the least significant byte and the following byte will be the most significant byte.

Branching

If we want to use branching we need to be able to mark certain points in a program, this can be done by labeling. A label is a single-byte relative offset; this means you can go forward and backwards with 256 bytes. You could compare branching in assembly with an if statement in C++ code. Labeling is also used to move around in local code, a.k.a. jumping.
There are different ways to branch:

  • BBC - BCS Branch if carry clear - set.
  • BEQ - NBE Branch if equal - not equal.
  • BMI - BPL Branch if minus - positive.
  • BVC - BVS Branch if overflow clear - set.

Jumping

Jumping is the same as branching but it is unconditionally executed and it has a 2-byte absolute address. There are 3 common instructions JMP(label) this jumps to the label. And then you have the dynamic duo JSR and RTS, these two mimic functions. The JSR instruction will push address minus one of the next instruction onto the stack. Then the RTS will pop this location and will jump to the location plus one.

The stack

The stack is always an important thing in programming. Values are pushed onto it and popped off it. The current depth of this stack is measured by the stack pointer. There are 2 stack instruction namely PHA which means push accumulator and PLA, pull accumulator. These instructions only work with register A.

Results

I made this project together with Celine Vandewalle. I stood in for:

  • Background implementation.
  • Start and pause button.
  • Further implementation of Ghunter the chicken.
  • Cloud implementatio

Links

Where I got the knowledge:

To see the assembly code in detail I kindly refer to the github repository.