6502commodore

6502 Assembly Loops


I'm working on 6502 assembly using Kick Assembler and its scripting language to compile and build the .prg/.sym files and working on the following problem.

Write a program using absolute indexed mode that will fill every 5th character on the screen with letter X.

The implementation I came up with looks like this.

:BasicUpstart2(main)

.const SCREEN_MEMORY1 = $0400

main:
    ldx #0                        // Initialize X register to 0
    lda #X_CHAR    

.for(var j = 0; j < 4; j++) {

loop:
    sta SCREEN_MEMORY + j*250, X  // Store X at the screen location indexed by X
.for(var i = 0; i < 5; i++ ) {
    inx                           // Increment X by 1
}
    cpx #$FF                      // Check if X has reached 255 (end of screen)
    bne loop                      // If not, continue looping

    ldx #0   
}

end:
    jmp end

This works fine but I would like to understand how to write the raw assembly code for this. I came up with the following implementation but I'm wondering if there less repetitive way to do this.

:BasicUpstart2(main)

.const SCREEN_MEMORY1 = $0400
.const SCREEN_MEMORY2 = $04FA
.const SCREEN_MEMORY3 = $05F4
.const SCREEN_MEMORY4 = $06EE
.const X_CHAR = 24

main:
    ldx #0                // Initialize X register to 0
    lda #X_CHAR

loop1:     
    sta SCREEN_MEMORY1, X // Store X at the screen location indexed by X
    inx
    inx
    inx
    inx
    inx
    cpx #$ff
    bne loop1

  ldx #0                // Initialize X register to 0

loop2:     
    sta SCREEN_MEMORY2, X // Store X at the screen location indexed by X
    inx
    inx
    inx
    inx
    inx
    cpx #$ff
    bne loop2

    ldx #0                // Initialize X register to 0

loop3:     
    sta SCREEN_MEMORY3, X // Store X at the screen location indexed by X
    inx
    inx
    inx
    inx
    inx
    cpx #$ff
    bne loop3

    ldx #0                // Initialize X register to 0

loop4:     
    sta SCREEN_MEMORY4, X // Store X at the screen location indexed by X
    inx
    inx
    inx
    inx
    inx
    cpx #$ff
    bne loop4

    end:
    jmp end

Is there a way to increment the original screen memory variable by x*250 in a similar way to the for loop?


Solution

  • One possibility is to do something like this:

    :BasicUpstart2(main)
    
    .const screen_base   = $0400
    .const fill_char     = 24
    
    * = $c000 "main"
    main:
      jsr fill_every_5
      rts
    
    fill_every_5:
      lda #fill_char
      ldx #$fa
    !:
      dex
      dex
      dex
      dex
      dex
      sta screen_base,x
      sta screen_base+(1*$fa),x
      sta screen_base+(2*$fa),x
      sta screen_base+(3*$fa),x
      bne !-
    
      rts
    

    We only need a single loop, but in each iteration we write into 4 different locations.