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)