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.
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.