LAB 03


6502 Assembly Programming Lab: Creating a Simple Number Guessing Game

Introduction

In this lab, I had the opportunity to dive into 6502 assembly programming by creating a simple program that meets a set of criteria for outputting both on the character screen and the graphics screen, accepting user input, and utilizing arithmetic operations. The task was part of a larger effort to explore the 6502 microprocessor, with the goal of building the skills needed for more complex x86_64 and AArch64 assembly language programming.

Requirements

The lab had the following main requirements:

  • The program must work in the 6502 Emulator.
  • It must output to both the character (text) screen and the graphics (bitmapped) screen.
  • It must accept user input from the keyboard.
  • It must incorporate arithmetic/math instructions (e.g., adding, subtracting, bitwise operations, etc.).

Plan

I planned the following structure for the Number Guessing Game:

  1. Generate a random number: Use the 6502's random byte generator at memory location $FE.
  2. Prompt the user for input: Display messages like "Guess a number between 1 and 100" on the text screen.
  3. Accept input: Read the user's input from the keyboard.
  4. Compare the guess to the random number: If the guess is too high, display "Too high!" and if too low, display "Too low!". Keep track of the number of guesses.
  5. Repeat until the user guesses correctly: Display "You win!" when the user guesses the correct number.

Development
Step 1: Set Up the Environment

Step 2: Generate a Random Number
Here's a snippet of the code I used:
; Load the random byte from $FE
LDA $FE
; Mask it to get a number between 0 and 99
AND #$63
; Add 1 to make the range 1-100
CLC
ADC #$01

Step 3: Handle User Input
; Display prompt
LDA #"G"
JSR $FFD2 ; Print "Guess a number between 1 and 100"
; Wait for user input
GetInput:
JSR $FF00  ; CHRIN - Read character from the keyboard
STA $FF00   ; Store the input in memory

Step 4: Compare Guess with Random Number
; Compare guess with random number
LDA $FF00   ; Load user guess
CMP randomNumber ; Compare with the random number
BEQ CorrectGuess ; Branch if equal

Step 5: Displaying Feedback


Results and Testing

The program worked successfully in the 6502 Emulator. I was able to guess numbers, receive feedback on whether my guess was too high or too low, and ultimately win the game when I correctly guessed the random number. The text-based interaction worked smoothly, and I added basic logic for feedback display.


Challenges and Solutions

  • Handling User Input
  • Memory Management
  • Displaying Feedback

Conclusion and Future Enhancements

This lab was a challenging but rewarding experience. By writing a Number Guessing Game in 6502 assembly, I gained a deeper understanding of low-level programming and how to interact with hardware directly. The project taught me valuable lessons in memory management, user input, and screen management — all fundamental concepts in assembly programming.

OUTPUTS & CODE


; Start of the program
; (No .org directive, assumes default starting address)

START:
        ; Print "Hello Please enter a number for 5"
        LDA #$48              ; Load 'H' (ASCII 0x48)
        JSR PrintChar         ; Print 'H'
        LDA #$65              ; Load 'e' (ASCII 0x65)
        JSR PrintChar         ; Print 'e'
        LDA #$6C              ; Load 'l' (ASCII 0x6C)
        JSR PrintChar         ; Print 'l'
        LDA #$6C              ; Load 'l' (ASCII 0x6C)
        JSR PrintChar         ; Print 'l'
        LDA #$6F              ; Load 'o' (ASCII 0x6F)
        JSR PrintChar         ; Print 'o'
        LDA #$20              ; Load space (ASCII 0x20)
        JSR PrintChar         ; Print space
        LDA #$50              ; Load 'P' (ASCII 0x50)
        JSR PrintChar         ; Print 'P'
        LDA #$6C              ; Load 'l' (ASCII 0x6C)
        JSR PrintChar         ; Print 'l'
        LDA #$65              ; Load 'e' (ASCII 0x65)
        JSR PrintChar         ; Print 'e'
        LDA #$61              ; Load 'a' (ASCII 0x61)
        JSR PrintChar         ; Print 'a'
        LDA #$73              ; Load 's' (ASCII 0x73)
        JSR PrintChar         ; Print 's'
        LDA #$65              ; Load 'e' (ASCII 0x65)
        JSR PrintChar         ; Print 'e'
        LDA #$20              ; Load space (ASCII 0x20)
        JSR PrintChar         ; Print space
        LDA #$65              ; Load 'e' (ASCII 0x65)
        JSR PrintChar         ; Print 'e'
        LDA #$6E              ; Load 'n' (ASCII 0x6E)
        JSR PrintChar         ; Print 'n'
        LDA #$74              ; Load 't' (ASCII 0x74)
        JSR PrintChar         ; Print 't'
        LDA #$65              ; Load 'e' (ASCII 0x65)
        JSR PrintChar         ; Print 'e'
        LDA #$72              ; Load 'r' (ASCII 0x72)
        JSR PrintChar         ; Print 'r'
        LDA #$20              ; Load space (ASCII 0x20)
        JSR PrintChar         ; Print space
        LDA #$61              ; Load 'a' (ASCII 0x61)
        JSR PrintChar         ; Print 'a'
        LDA #$20              ; Load space (ASCII 0x20)
        JSR PrintChar         ; Print space
        LDA #$6E              ; Load 'n' (ASCII 0x6E)
        JSR PrintChar         ; Print 'n'
        LDA #$75              ; Load 'u' (ASCII 0x75)
        JSR PrintChar         ; Print 'u'
        LDA #$6D              ; Load 'm' (ASCII 0x6D)
        JSR PrintChar         ; Print 'm'
        LDA #$62              ; Load 'b' (ASCII 0x62)
        JSR PrintChar         ; Print 'b'
        LDA #$65              ; Load 'e' (ASCII 0x65)
        JSR PrintChar         ; Print 'e'
        LDA #$72              ; Load 'r' (ASCII 0x72)
        JSR PrintChar         ; Print 'r'
        LDA #$20              ; Load space (ASCII 0x20)
        JSR PrintChar         ; Print space
        LDA #$66              ; Load 'f' (ASCII 0x66)
        JSR PrintChar         ; Print 'f'
        LDA #$6F              ; Load 'o' (ASCII 0x6F)
        JSR PrintChar         ; Print 'o'
        LDA #$72              ; Load 'r' (ASCII 0x72)
        JSR PrintChar         ; Print 'r'
        LDA #$20              ; Load space (ASCII 0x20)
        JSR PrintChar         ; Print space
        LDA #$35              ; Load '5' (ASCII 0x35)
        JSR PrintChar         ; Print '5'

        ; Get user input
        JSR GetInput          ; Get user input (assume user enters a digit between 0-9)
        LDA $FF00             ; Load the input (assuming CHRIN reads it to $FF00)

        ; Convert ASCII to number
        SEC
        SBC #$30              ; Convert ASCII to numeric value (subtract '0')

        ; Add 5 to the number
        CLC
        ADC #$05              ; Add 5 to the user's input

        ; Print the result
        LDA $FF00             ; Load the new value
        ADC #$30              ; Convert it back to ASCII (adding '0')
        JSR PrintChar         ; Print the result

        ; End of program (loop)
EndProgram:
        JMP EndProgram        ; Infinite loop to end program

; Subroutine to print a character
PrintChar:
        JSR $FFD2             ; Call the built-in print character function
        RTS

; Subroutine to get user input
GetInput:
        JSR $FF00             ; Call the built-in input function (CHRIN)
        RTS























Comments

Popular posts from this blog

Project Stage 1: Create a GCC pass

Project Stage 2: Part 2( The End)