SPO600 - Lab 3: 6502 Program Lab: Inches to Feet Converter
In this lab, I used the 6502 assembly language to build a simple inches-to-foot converter. This project allowed me to experiment with arithmetic operations, keyboard input handling, and direct screen output without relying on ROM routines. This hands-on experience also helped me prepare for more advanced assembly languages like x86_64 and AArch64.
Resources
During the lab, I used a variety of resources, including:
6502 documentation provides detailed information about the 6502 architecture and instruction set.
6502 Emulator: For testing and debugging code.
6502 Math and Procedures: A reference book for arithmetic operations and control flow.
Sample code demonstrates graphical output and keyboard input handling.
Project Concept
My project is a simple calculator that converts a specified number of inches to feet. In this program, the user enters an inch number, and when they press Enter, the program calculates and displays the corresponding number of feet. This simple conversion necessitated careful consideration of input handling and arithmetic operations, laying a solid foundation for assembly language programming.
Challenges & Problem-Solving
One of the most difficult challenges I faced was implementing custom keyboard input handling. I needed to create a responsive system that not only accepted input but also displayed a blinking cursor. To address this, I designed the input routine to manage key presses, display entered characters directly on the screen, and handle backspace functionality.
Another challenge was converting inches to feet. Initially, I considered using direct division, which can be complicated in assembly. Instead, I used bit shifts to approximate the division, which simplified the logic while remaining efficient.
Despite the successful input and conversion processes, I encountered a significant issue when displaying the final result. The program was supposed to display the calculated feet value directly on the screen, but it did not work as intended. I suspect the problem is with the memory addressing or the way I implemented the display logic, which I intend to investigate further.
Program Structure
I organised my program into several key sections:
Keyboard Input Handling: This section handles user input by providing backspace functionality and displaying a blinking cursor.
Arithmetic Operations: Inches are converted to feet using bitwise shifts to achieve division by 12.
Character Screen Output: The result is displayed directly on the character screen after being written to screen memory.
Code
; Define the screen memory location
SCREEN = $f000 ; Location of screen memory
; Main Program Entry Point
start:
jsr $ff81 ; Initialize and clear the screen
jsr getInput ; Get user input in inches
jsr convertToFeet ; Convert inches to feet
jsr displayResult ; Display the result in feet
brk ; Break to stop the program
; Subroutine: Get user input in inches (custom input handling)
getInput:
ldx #$00 ; Clear the X register (accumulator for inches)
ldy #$00 ; Start with index Y = 0
input_loop:
ldx #$00 ; Reset X for the blinking cursor
next:
inx ; Increment index for the blinking cursor
cpx #$10 ; Check for maximum character limit (16 characters)
bne check
lda SCREEN,y ; Get character from screen memory
eor #$80 ; Toggle bit 7 for blinking cursor
sta SCREEN,y ; Store back with cursor
check:
lda $ff ; Check for key press (poll input)
beq next ; If no key press, keep waiting
ldx #$00 ; Reset blinking counter
stx $ff ; Clear key press flag
cmp #$0D ; Check if Enter is pressed (ASCII 13)
beq input_done ; If Enter is pressed, end input
cmp #$08 ; Check for backspace
bne print ; If not backspace, print the character
lda SCREEN,y ; Read the screen
and #$7F ; Clear the character on the screen
sta SCREEN,y ; Update the screen to show blank
dey ; Move back one character if backspace
jmp next ; Continue input loop
print:
sta SCREEN,y ; Store the input character at screen position
iny ; Move to the next character position
jmp input_loop ; Continue typing
input_done:
rts ; Return when input is done
; Subroutine: Convert inches to feet (1 foot = 12 inches)
convertToFeet:
lda $00 ; Load the total inches value from memory
lsr ; Divide by 2 (logical shift right)
lsr ; Divide by 2 again (total divide by 4)
lsr ; Divide by 2 again (total divide by 8, so effectively divide by 12)
sta $01 ; Store the number of feet in memory
rts ; Return from subroutine
; Subroutine: Display the result (in feet) on the character screen
displayResult:
ldy #$00 ; Reset Y index for displaying the result
lda $01 ; Load the total feet (result) from memory
jsr convertToASCII ; Convert the result into ASCII characters
jsr displayNumber ; Display the converted result on the screen
rts ; Return from subroutine
; Subroutine: Convert number to ASCII
convertToASCII:
clc ; Clear carry flag
adc #$30 ; Convert binary number to ASCII
sta resultBuffer ; Store the ASCII result in the buffer
rts ; Return from subroutine
; Subroutine: Display the converted number
displayNumber:
ldy #$00 ; Reset index for displaying the number
displayLoop:
lda resultBuffer ; Load ASCII result from the buffer
beq doneNumber ; If NULL terminator is found, stop displaying
sta SCREEN,Y ; Output the character to the screen memory (SCREEN)
iny ; Move to the next character
bne displayLoop ; Continue to display the result
doneNumber:
rts ; Return from subroutine
; Buffer for storing the result digits
resultBuffer:
dcb 0 ; Buffer to hold the ASCII result
The conversion from inches to feet presented difficulties, particularly when performing division. By using bit shifts, I simplified the logic while learning about binary manipulation and arithmetic operations in assembly language.
Looking ahead, I intend to add error handling for non-numerical inputs and expand the program to support more conversions. I am also interested in performance optimisation, which will help me improve my assembly language coding skills.
Overall, this project not only improved my technical skills but also fuelled my desire to take on new challenges in assembly programming.
Nhận xét
Đăng nhận xét