assembly - 如何在Z80 ASM中重复将两个字节写入RAM block

标签 assembly texas-instruments z80

我正在尝试向使用Zilog eZ80 CPU的TI-84 Plus CE-T计算器的VRAM写入两个字节(颜色值)。 VRAM从0xD40000开始,长度为0x25800字节。计算器具有一个称为MemSet的内置系统调用,该系统调用用一个字节填充了一块内存,但是我希望它在两个不同的值之间交替并将它们存储在内存中。我尝试使用以下代码:

#include "includes\ti84pce.inc"

    .assume ADL=1
    .org userMem-2
    .db tExtTok,tAsm84CeCmp

    call  _homeup
    call  _ClrScrnFull
    ld    hl,13893632     ; = D40000, vram start
    ld    bc,153600       ; = 025800, count/vram length
j1:
    ld    (hl),31         ; set first byte
    inc   hl
    dec   bc
    jr    z,j2            ; jump to end if count==0
    ld    (hl),0          ; set second byte
    inc   hl
    dec   bc
    jr    z,j2            ; jump to end if count==0
    jp    j1              ; loop
j2:
    call  _GetKey
    call  _ClrScrnFull
    ret

我希望它将31 00 31 00 31 00 ...输出到从0xD40000开始的内存中,但是相反,它似乎只更改第一个字节,然后跳到末尾。有想法该怎么解决这个吗?

最佳答案

tum_'s答案的变化比dec bc快于零测试机制,从而实现了循环。

    LD   SP,$D65800    ; <end of VRAM>: 0xD40000+0x25800
    LD   BC,$004B      ; 0x4B many times (in C) the 256x inner loop (B=0)
        ; that results into 0x4B00 repeats of loop, which when 8 bytes per loop
        ; are set makes the total 0x25800 bytes (VRAM size)
        ; (if you would unroll it for more than 8 bytes, it will be a bit more
        ; tricky to calculate the initial BC to get correct amount of looping)
        ; (not that much tricky, just a tiny bit)
    LD   HL,31         ; H <- 0, L <- 31
.L1
    PUSH HL            ; (SP – 2) <- L, (SP – 1) <- H, SP <- SP - 2
    PUSH HL            ; set 8 bytes in each iteration
    PUSH HL
    PUSH HL
    DJNZ .L1           ; loop by B value (in this example it starts as 0 => 256x loop)
    DEC  C             ; loop by C ("outer" counter)
    JR   NZ,.L1        ; btw JP is faster than JR on original Z80, but not on eZ80
.END

(顺便说一句,我从来没有做过eZ80编程,也没有在调试器中验证这一点,所以这有点假设...实际上是在考虑,eZ80上的push不是32位吗?hl的初始化应该是ld hl,$001F001F用单个push设置四个字节,并且循环的内部应该只有两个push hl)

(但是我做了Z80编程的 ton ,所以这就是为什么我什至不愿对此主题发表评论,即使我以前从未见过eZ80代码)

编辑:事实证明eZ80推送是24位的,即上面的代码将产生错误的结果。它当然可以很容易地解决(因为问题是实现细节,而不是原则),例如:
    LD   SP,$D65800    ; <end of VRAM>: 0xD40000+0x25800
    LD   BC,$0014      ; 0x14 many times (in C) the 256x inner loop (B=0)
        ; that results into 0x1400 repeats of loop, which with 30 bytes per
        ; loop set makes the total 0x25800 bytes (VRAM size)
    LD   HL,$1F001F    ; will set bytes 31,  0, 31
    LD   DE,$001F00    ; will set bytes  0, 31,  0
.L1
    PUSH DE
    PUSH HL
        ; here SP = SP-6, and 6 bytes 31, 0, 31, 0, 31, 0 were set
    PUSH DE
    PUSH HL
    PUSH DE
    PUSH HL
    PUSH DE
    PUSH HL
    PUSH DE
    PUSH HL            ; unrolled 5 times to set 30 bytes in total
    DJNZ .L1           ; loop by B value (in this example it starts as 0 => 256x loop)
    DEC  C             ; loop by C ("outer" counter)
    JR   NZ,.L1

关于assembly - 如何在Z80 ASM中重复将两个字节写入RAM block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57483503/

相关文章:

c# - 如果调用堆栈被破坏,是只会使当前线程崩溃,还是让我的整个应用程序崩溃?

assembly - 将两个字符减去 rax

c - C 中如何返回 void* 指针?

texas-instruments - 将德州仪器 TI-84 Plus CE 连接到 Ubuntu 计算机

assembly - 8086汇编,关于PTR操作符

c - 从 DSP C6748 的 Matlab-Simulink 模型生成 C 代码

c - 从CLIB到DLIB:size_t未定义

java - Z80 DAA 实现和 Blagg 的测试 rom 问题

Windows XP 与 Windows 7 上的 Java 计时精度

vb.net - 如何在 VB.NET 中将十六进制偏移量转换为两字节指针?