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:
- Generate a random number: Use the 6502's random byte generator at memory location
$FE
. - Prompt the user for input: Display messages like "Guess a number between 1 and 100" on the text screen.
- Accept input: Read the user's input from the keyboard.
- 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.
- 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
Post a Comment