For this lab we were tasked with creating two programs from a list in 6502 assembly code. These tasks ranged in difficulty though some things were made far easier by the introduction of ROM routines which I will explain a bit later. The two tasks which out group decided on were the calculator and the colour selector. We chose these two for a couple of reasons, the largest being that we all felt most confident in out own ability to get done these two tasks over any others. So with our tasks in hand we set out to get an understanding on ROM Routines.
ROM routines are basically snippets of code saved in the memory of the chip, In order to access these you simply need to start a subroutine and the right address and it will run the subroutine as if it were code which you wrote. The Routines given to us did things which previously requited many lines of code now in just one with smart use of the various registers in order to supply input to these routines.
Now before getting to the code for the adder it is important to note that we were never able to get the blinking cursor to work properly, though the rest of the program works for sure. Now here is the full source code which will be explained bellow.
; 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
define NUMBERA $10;
define NUMBERB $20;
jsr SCINIT
mainLoop:
ldy #$00
jsr char1
jsr input
jsr storeA
ldy #$00
jsr char2
jsr input
jsr storeB
ldy #$00
jsr charR
jsr printAdd
jmp mainLoop
input:
SEC
jsr PLOT
ldx #$15
CLC
jsr PLOT
inLoop:
SEC
jsr PLOT
jsr CHRIN
charCheck:
cmp #$00
beq inLoop
cmp #$81
beq right
cmp #$83
beq left
cmp #$0d
beq next
drawNum:
cmp #$30
bcc inLoop
clc
cmp #$3a
bcs inLoop
jsr CHROUT
SEC
jsr PLOT
cpx #$17
bne inLoop
dex
CLC
jsr PLOT
jmp inLoop
left: cpx #$15
beq inLoop
jsr CHROUT
jmp inLoop
right: cpx #$16
beq inLoop
jsr CHROUT
jmp inLoop
next:
SEC
jsr PLOT
ldx #$15
CLC
jsr PLOT
SEC
jsr PLOT
CLC
SBC #$2F
ASL
ASL
ASL
ASL
PHA
ldx #$16
CLC
jsr PLOT
SEC
jsr PLOT
CLC
SBC #$2F
PHA
ldx #$00
iny
CLC
jsr PLOT
SEC
jsr PLOT
PLA
TAX
PLA
rts
storeA:
sta NUMBERA
txa
eor NUMBERA
sta NUMBERA
rts
storeB:
sta NUMBERB
txa
eor NUMBERB
sta NUMBERB
rts
printAdd:
SEC
jsr PLOT
ldx #$15
CLC
jsr PLOT
SEC
jsr PLOT
SED
lda NUMBERA
adc NUMBERB
CLD
pha
bcc outputAddition
ldx #$14
CLC
jsr PLOT
SEC
jsr PLOT
lda #$31
jsr CHROUT
outputAddition:
pla
pha
LSR
LSR
LSR
LSR
clc
adc #$30
jsr CHROUT
pla
and #$0F
clc
adc #$30
jsr CHROUT
SEC
jsr PLOT
ldx #$00
iny
CLC
jsr PLOT
rts
char1: lda firstDigit,y
beq charRet
jsr CHROUT
iny
bne char1
char2: lda secondDigit,y
beq charRet
jsr CHROUT
iny
bne char2
charR: lda result,y
beq charRet
jsr CHROUT
iny
bne charR
charRet:
rts
firstDigit:
dcb "E","N","T","E","R",32,"F","I","R","S","T",32,"D","I","G","I","T",":",32,32,32,"0","0"
dcb 00
secondDigit:
dcb "E","N","T","E","R",32,"S","E","C","O","N","D",32,"D","I","G","I","T",":",32,32,"0","0"
dcb 00
result:
dcb "R","E","S","U","L","T",":"
dcb 00
The Adder is actually quite a simple program especially thanks to ROM routines. The writing went through a few revisions before settling on the final result, this is due to poor user of subroutines in previous incarnations as well as unfamiliarity with the ROM routines. Now speaking of the ROM routines let's discuss what they are accomplishing for us here.
there are three important ROM routines to making this code as compact as it is, the first if CHROUT, this will spit out a character onto the screen and then move the cursor over one, very simple but extremely useful. It does this by simply checking the accumulator for the value and then putting it at the current cursor location, the next routine used is the compliment to CHROUT, CHRIN. As the name implies CHRIN takes a character input, this input is stored in the accumulator which means it can be used in conjunction with CHROUT to print input to the screen. The last important ROM routines we have is PLOT. This routine has two functions depending on the state of the carry flag. Either it gets the current cursor position and returns the value of the character there, or it sets the current cursor position based on what is currently in x and y.
Using these Tools the code goes through a main loop which utilizes a few subroutines in order to keep it as readable as possible. This main loop is only 12 lines but does all the work of the program vie the subroutines it calls. Let's take a closer look at it.
mainLoop:
ldy #$00
jsr char1
jsr input
jsr storeA
ldy #$00
jsr char2
jsr input
jsr storeB
ldy #$00
jsr charR
jsr printAdd
jmp mainLoop
So the first step is to set y to a known value, this allows char1 to work properly as it will print onto the screen the instructions to enter the first input and the start location is whatever y is. Next we get the first user input. This is done through quite complex code which I will explain further down. following this it stores the first number then it does it all again for the second number. After this it prints the result text followed by doing the actual addition and printing those results, this whole thing then loops allowing the program to keep taking inputs.
Now let's break down a couple of the more important components there, namely input, storeX and printAdd. input is how we get out user input and as we are simply making a calculator only certain characters are allowed we do this by limiting the values that can be read by CHRIN, if it gets anything else we simply ask it to try again. This ensures we are either getting a number, an arrow key, or the enter key. When a character is input, it will also do a check on whether or not the input field is on the second digit in order to ensure you can only write two digits. Next storeA and storeB which take the numbers provided to them and store them in different addresses, fairly simple. Lastly printAdd which does the actual adding. This subroutine switches to decimal mode before adding the two values stored in the previous subroutines together. It then checks to see if there was a carry and if there was it draws a 1 before the number, before then drawing the output of the addition.
All of this put together and we have a working, though not perfect Adder in 6502 assembly.
No comments:
Post a Comment