Assembly 如何在MOS 6502的asm中创建延迟

Assembly 如何在MOS 6502的asm中创建延迟,assembly,delay,6502,Assembly,Delay,6502,我是ASM新手,我正在尝试解决如何为以下代码创建延迟: org $1000 loop: inc $d021 jmp loop 例如: loop: ldx $d021 inx stx $d021 cpx #100 bne loop 我想评论已经足够清楚了 更改每帧颜色的代码示例(1/50秒) 用于每秒更改颜色的代码示例 counter = $fa ; a zeropage address to be used as a counter

我是ASM新手,我正在尝试解决如何为以下代码创建延迟:

org $1000

loop: inc $d021
    jmp loop
例如:

loop: ldx $d021
      inx
      stx $d021
      cpx #100
      bne loop

我想评论已经足够清楚了

更改每帧颜色的代码示例(1/50秒)

用于每秒更改颜色的代码示例

counter = $fa ; a zeropage address to be used as a counter

        lda #$00    ; reset
        sta counter ; counter

        sei       ; enable interrupts

loop1:  lda #$fb  ; wait for vertical retrace
loop2:  cmp $d012 ; until it reaches 251th raster line ($fb)
        bne loop2 ; which is out of the inner screen area

        inc counter ; increase frame counter
        lda counter ; check if counter
        cmp #$32    ; reached 50
        bne out     ; if not, pass the color changing routine

        lda #$00    ; reset
        sta counter ; counter

        inc $d021 ; increase background color
out:
        lda $d012 ; make sure we reached
loop3:  cmp $d012 ; the next raster line so next time we
        beq loop3 ; should catch the same line next frame

        jmp loop1 ; jump to main loop

这个怎么样?这将更改背景,等待4秒钟,然后再次更改。永远重复

注意,您可以将秒数更改为0到255之间的任何值

这适用于
NTSC
机器,但您可以将
PAL
60
更改为
50

main:
    inc $D021

    ldx #4          //  Wait 4 seconds
loop1:
    ldy #60
loop2:

waitvb:
    bit $D011
    bpl waitvb
waitvb2:
    bit $D011
    bmi waitvb2

    dey
    bne loop2
    dex
    bne loop1

    jmp main

如果您可以确保代码不会跨越页面边界,一种有用的方法是在RAM中的某个位置有一对字节,它将保存一个计算出的跳转地址,并使用间接跳转到如下内容:

TableStart:
    cmp #$C9
    cmp #$C9
    cmp #$C9
    cmp #$C9
    cmp #$C9
    ...
TableEnd:
    nop
如果跳转向量指向tableEnd,代码将到达指令 在七个周期后进行NOP。如果它前面指向一个字节,则指向八个字节 周期。两个字节之前,九个周期,等等。设置跳转向量 可能需要一段时间,但延迟本身可以顺利调整 以单周期增量从七个周期到任何更高的值。旗帜
将被丢弃,但没有寄存器会受到影响。

是的,这只是一个更改前景程序。你是说背景吗?如果“延迟”是指等待下一条扫描线,那么添加一个等待
$d012
更改的内循环。不,我是指等待一秒钟,然后更改颜色(抱歉混淆)然后等待
$d012
更改320*50次,或者使用光栅中断对帧进行计数。这不会每秒更改$d021一次,而是每15个周期更改一次,直到其“值为#100”(这是完全可变的,因为我们不知道从$d021开始是什么).在一开始,user3049038只写了一个循环,所以我为他写了一个循环。没有更多关于$d021是HW寄存器的信息-所以我的答案是正确的。$D020/01是我们恐龙非常熟悉的地址。特别是在与6502/10的结合使用时也许是C64恐龙。我有Atari 800xl,所以我不知道这个寄存器:)你可以用Y代替零页和A。不用增加计数器,而是减少它,这样你就可以隐式地在Y上使用BNE。更短,更快,更惯用。请参阅我的编辑请求。由于我喜欢编写256字节的介绍,我使用了许多技巧,如自我修改代码、非法操作码、共享寄存器值等。但此代码示例是专门为说“我是ASM新手”的人编写的。因此,这既不是大小优化的源代码,也不是周期优化的源代码。这是一个供初学者使用的代码示例,我认为反向循环可能会混淆它们。我认为使用零页make比使用Y寄存器更复杂,无论您如何循环(反向或正向),特别是如果a用于两个目的。我的建议不是减少代码大小或周期数(这是一个副作用),而是增加可读性。也许使用Y寄存器转发,加上显式的CPY,会是一个更好的初学者解决方案。
TableStart:
    cmp #$C9
    cmp #$C9
    cmp #$C9
    cmp #$C9
    cmp #$C9
    ...
TableEnd:
    nop