gus

Posted on

6502 Math and Strings Part III

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

clc
sta \$17
lda \$18     ; carry to high byte if needed
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

clc
sta \$17
lda \$18     ; carry to high byte if needed
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

clc
sta \$17
lda \$18     ; carry to high byte if needed
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.