Add Calculator
In this post, I will be discussing how we implemented opcode using 6502 chip architecture to take user input of 2 digits and add them together to get a final result. This calculator will take only positive numbers ranging from 0-99. This will be done using a combination of instructions and ROM routines built into the chip.
Setting the Cursor Position
; ROM routines
define SCINIT $ff81 ; initialize/clear screen
define CHRIN $ffcf ; input character from keyboard
define CHROUT $ffd2 ; output character to screen
define SCREEN $ffed ; get screen size
define PLOT $fff0 ; get/set cursor coordinates
jsr SCINIT
ldy #$00
cursorPos: ;set cursor position
clc ;clear carry for PLOT
ldy #$03 ;set coordinate Y
ldx #$00 ;set coordinate X
jsr PLOT ;call PLOT
jmp idle
idle:
lda $f000,y
eor #$80
sta $f000,y
jmp cursorPos
Here is a code using plot to set the cursor position for where the user will begin to input their unsigned integers to calculate. The label cursorPos will set this position. Once the position is set, we include the idle label. This label allows the user to see where their current position is on the character display. The next step is to take user input and display it onto the character display box.
Accepting User Input
cursorPos: ;set cursor position
clc ;clear carry for PLOT
ldy #$03 ;set coordinate Y
ldx #$00 ;set coordinate X
jsr PLOT ;call PLOT
input:
jsr CHRIN
bne display
jmp idle
display:
jsr CHROUT
iny
jmp input
idle:
lda $f000,y
eor #$80
sta $f000,y
lda $ff
jmp input
We have added the labels display and input. I will first explain what the input label’s main function is. Calling the ROM routine, CHRIN, accepts a user input and stores it in the Accumulator and using branch if not equal (bne) is how we will be accepting user input and displaying it onto the character display box. If there is nothing stored in the accumulator, then the program will skip the branch to display and jump to the label idle. Although, if CHRIN returns a character to the accumulator, then the display label will be called. Once in the display label, CHROUT will take what ever is stored in the accumulator and output it to the character display box.
Notice that normally we would have to manage the memory location $ff, if we were using only instructions. CHROUT and CHRIN remove the hassle of managing $ff, which the chip architecture uses to store the last key pressed from the keyboard.
Store User Input
; ROM routines
define SCINIT $ff81 ; initialize/clear screen
define CHRIN $ffcf ; input character from keyboard
define CHROUT $ffd2 ; output character to screen
define SCREEN $ffed ; get screen size
define PLOT $fff0 ; get/set cursor coordinates
jsr SCINIT
ldy #$00
lda #$00
sta $20
cursorPos: ;set cursor position
clc ;clear carry for PLOT
ldy #$03 ;set coordinate Y
ldx #$00 ;set coordinate X
jsr PLOT ;call PLOT
input:
jsr CHRIN
bne display
jmp idle
display:
jsr CHROUT
iny
cmp #$2b
bne store
beq input2
jmp input
store2:
sta $21 ;store second user input into memory location $21
brk
rts
store:
sta $20 ;store first user input into memory location $20
jmp input
add:
clc
lda $20
adc $21
jsr CHROUT
brk ;end of program
idle:
lda $f000,y
eor #$80
sta $f000,y
lda $ff
jmp input
input2:
jsr CHRIN
bne display2
jmp idle2
display2:
jsr CHROUT
iny
jsr store2
cmp #$0d
beq add
jmp input2
idle2:
lda $f000,y
eor #$80
sta $f000,y
lda $ff
jmp input2
brk ;in case program runs pass
In expanding our code, we have created a label called store. This label’s purpose is to store the first digit inputted by user into memory location $20. Once the first input was stored, we had to figure out a way to store the second digit that a user inputs. This is where we expanded our code to include 4 more labels, store2, input2, display2, and idle2. These label’s purposes are the same as the previous but they take into account that the user had already previously entered a digit value.
On line 28, 29, and 30 we added 3 lines of code to out label display. We compare the value entered by a user, which is returned to the accumulator, and compare to #$2b. This value is represented by a ‘+’ ASCII character. If the accumulator does not contain #$2b, then we know that the user has yet to enter the first value, otherwise we branch to our 4 labels that we created.
Not much has change for labels input2 and idle2, they are the same as the previous ones we have created. What has been modified that has to be highlighted is label’s store2 and display2. In store2, we would store the second value into memory location $21. The program knows that it is the second value because of our display label. If #$2b is returned to our accumulator, the program understands that following the user input should be stored and used as the second value when we do our addition.
Things to be Completed
Adding two values in memory – We have stored both of the user input into memory locations $20 and $21. We found that if we stored the number 1, we would get the hex ASCII value of 31. We need to convert our digit into an ASCII character to display.
Conclusion
In Conclusion, I have found that using CHROUT and CHRIN have been easier to manage then only using instructions. The built-in management of last key pressed being returned to the accumulator has allowed me to avoid managing memory location $ff. PLOT has been helpful in determining the cursor position. When dealing with the character display box, the rows and pages do not necessarily mean the first pixel on the row. Using PLOT, which handles coordinates in rows and columns, has helped me manage new lines. I would recommend using ROM routines because they handle a lot of management in the back end.