This is part 3 in a series on writing a program in assembly for the 6502 processor. You can find part 1 here and part 2 here.
After covering the necessary tools for building our program, today I'm getting into the coding. I've chosen to write a simple program to get input from the user and determine if a number is even or odd using the Logical Shift Right I discussed in my last post.
First up, I set up a subroutine to draw the result of the operation on the bitmapped display. Referencing the example here I wrote code to display "Even" or "Odd" depending on the result.
Here's the code for just the "Odd" portion. From here I need to add character input, logic to perform the LSR operation, logic to get the remainder (through the carry flag I believe?) and finally print one of the two results to the bitmapped display.
define WIDTH 32 ; width of sprite
define HEIGHT 8 ; height of sprite
done: brk
; win sprite print subroutine
lda #$26 ; create a pointer at $26
sta $17 ; which points to where
lda #$02 ; the sprite should be drawn
sta $18
lda #$00 ; number of rows we've drawn
sta $19 ; is stored in $19
ldx #$00 ; index for data
ldy #$00 ; index for screen column
odddraw:lda oddmsg ,x
sta ($17),y
inx
iny
cpy #WIDTH
bne odddraw
inc $19 ; increment row counter
lda #HEIGHT ; are we done yet?
cmp $19
beq done ; ...exit if we are
lda $17 ; load pointer
clc
adc #$20 ; add 32 to drop one row
sta $17
lda $18 ; carry to high byte if needed
adc #$00
sta $18
ldy #$00
beq odddraw
; sprite
oddmsg:
dcb 00,18,18,00,00,00,18,18,00,00,00,18,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 18,00,00,18,00,00,18,00,18,00,00,18,00,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 18,00,00,18,00,00,18,00,00,18,00,18,00,00,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 18,00,00,18,00,00,18,00,00,18,00,18,00,00,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 18,00,00,18,00,00,18,00,18,00,00,18,00,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 00,18,18,00,00,00,18,18,00,00,00,18,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
Unfortunately I ran into some issues with my program's execution so I'm going to have to leave it at that and move on, but the code for what I wrote is as follows:
; ROM Subroutines
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
;CONSTANTS
define WIDTH 32 ; width of sprite
define HEIGHT 8 ; height of sprite
define INPUT $10
define NUM $00
ldy #$00
init: lda msg,y
beq getnum
jsr CHROUT
iny
bne init
getnum:
lda #NUM
sta INPUT
ldy #$00
jsr CHRIN
cmp #$00
beq getnum
cmp #$30
bmi getnum
cmp #$39
bpl getnum
jsr CHROUT
sta input
jmp modulomsg
modulomsg:
lda msg2,y
beq printinput
jsr CHROUT
iny
bne modulomsg
printinput:
lda INPUT
jsr CHROUT
jmp result
result:
lda input
clc
jsr chrout
lsr x
lda x
jsr CHROUT
bcc evendraw
bcs odddraw
msg:
dcb "E","n","t","e","r",32,"a",32,"n","u","m","b","e","r",":",32,0,
msg2:
dcb $0d,$0d,$0d,"Y","o","u",32,"e","n","t","e","r","e","d",":",32,0
done: brk
odddraw:
lda #$20 ; create a pointer at $26
sta $17 ; which points to where
lda #$02 ; the sprite should be drawn
sta $18
lda #$00 ; number of rows we've drawn
sta $19 ; is stored in $0a
ldx #$00 ; index for data
ldy #$00 ; index for screen column
lda odddata ,x
sta ($17),y
inx
iny
cpy #WIDTH
bne odddraw
inc $19 ; increment row counter
lda #HEIGHT ; are we done yet?
cmp $19
beq done ; ...exit if we are
lda $17 ; load pointer
clc
adc #$20 ; add 32 to drop one row
sta $17
lda $18 ; carry to high byte if needed
adc #$00
sta $18
ldy #$00
beq odddraw
evendraw:
lda #$20 ; create a pointer at $20
sta $17 ; which points to where
lda #$02 ; the sprite should be drawn
sta $18
lda #$00 ; number of rows we've drawn
sta $19 ; is stored in $0a
ldx #$00 ; index for data
ldy #$00 ; index for screen column
lda evendata ,x
sta ($17),y
inx
iny
cpy #WIDTH
bne evendraw
inc $19 ; increment row counter
lda #HEIGHT ; are we done yet?
cmp $19
beq done ; ...exit if we are
lda $17 ; load pointer
clc
adc #$20 ; add 32 to drop one row
sta $17
lda $18 ; carry to high byte if needed
adc #$00
sta $18
ldy #$00
beq evendraw
; odd sprite
odddata:
dcb 00,18,18,00,00,00,18,18,00,00,00,18,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 18,00,00,18,00,00,18,00,18,00,00,18,00,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 18,00,00,18,00,00,18,00,00,18,00,18,00,00,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 18,00,00,18,00,00,18,00,00,18,00,18,00,00,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 18,00,00,18,00,00,18,00,18,00,00,18,00,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 00,18,18,00,00,00,18,18,00,00,00,18,18,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
; even sprite
evendata:
dcb 05,05,05,05,00,00,05,00,00,00,00,05,00,00,05,05,05,05,00,00,05,05,00,00,05,00,00,00,00,00,00,00
dcb 05,00,00,00,00,00,05,00,00,00,00,05,00,00,05,00,00,00,00,00,05,05,00,00,05,00,00,00,00,00,00,00
dcb 05,05,05,05,00,00,00,05,00,00,05,00,00,00,05,05,05,05,00,00,05,05,05,00,05,00,00,00,00,00,00,00
dcb 05,00,00,00,00,00,00,05,00,00,05,00,00,00,05,00,00,00,00,00,05,00,05,00,05,00,00,00,00,00,00,00
dcb 05,00,00,00,00,00,00,00,05,05,00,00,00,00,05,00,00,00,00,00,05,00,00,05,05,00,00,00,00,00,00,00
dcb 05,05,05,05,00,00,00,00,05,05,00,00,00,00,05,05,05,05,00,00,05,00,00,05,05,00,00,00,00,00,00,00
dcb 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
dcb 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
For some reason it stops running after the character input is received and the subroutines for getting the result of the LSR and printing the appropriate message aren't triggered. And that concludes this series on math and strings in assembly on the 6502, hopefully it's been informative.
Top comments (0)