我有一个循环0x167次的代码,写入屏幕。 我想要发生的是脚本循环三次。
我的剧本:
d322 21A0C3 LD HL,C3A0h
d323 016801 LD BC,0168h
d324 110300 LD DE,0003h
d325 00 NOP
.
.
.
d330 0B DEC BC
d331 75 LD (HL),L
d332 00 NOP
d333 23 INC HL
d334 00 NOP
.
.
.
d33f 78 LD A,B
d340 B1 OR C
d341 C22BD3 JP NZ,D32Bh
d344 7A LD A,D
d345 B3 OR E
d346 1B DEC DE
d347 00 NOP
d348 00 NOP
d349 C22BD3 JP NZ,D32B
d34c C9 RET
现在,它不再停留在应有的位置,而是继续进一步损坏内存,直到达到d325并导致脚本崩溃。你可能会说,我试图用DE作为循环的计数器。
请解释一下你的答案,我对此仍然很乏味。
答案 0 :(得分:0)
我的阅读就是你:
Set HL = 0xC3A0, BC = 0x0168, DE = 0x0003
do {
... something you've omitted ...
do {
bc--
[l] = hl
hl++
} while(bc)
was_positive = (DE > 0)
DE--
} while(was_positive)
因此外部循环将发生四次次,因为模式将是:
可能你想在比较之前做DEC?它是将DE与零进行比较的LD A, D / OR E
- 如果其位的确切为零,则表示它为零 - 后续的减量不会改变您已经计算的结果
在这种情况下,您将获得0x0168 + 4 * 0x10000次迭代= 0x40168次迭代。哪个甚至可能不是你想要的?这意味着你会多次覆盖内存中的每个地址。即使您的代码在ROM中是安全的,也会造成大量浪费的代码。
如果您打算循环3 * 0x0168次,那么还要记得重新加载BC。你只需让它下溢到0xffff并恢复。考虑切换初始加载的顺序,使BC最后,并更改外部分支以跳回到加载它的位置。
答案 1 :(得分:0)
问题是您在设置标志后递减DE
。代码的关键部分是:
LD A,D
OR E
DEC DE
JP NZ,D32B
将其更改为:
DEC DE
LD A,D
OR E
JP NZ,D32B
外部循环将运行3次而不是4.注意BC
循环正确处理并执行0x168次,而不是0x167,因此您可能想要更改它。
Z-80上的16位计数器很笨拙,因为16位递减不会设置任何标志。这就是为什么你需要代码将两个寄存器组合在一起作为在16位对等于零时设置Z标志的方法。
由于您只需要3次迭代,您可以使用一个8位寄存器并写入:
LD E,3
...
DEC E
JP NZ,D32B
正如Tommy的回复中所述,您还需要在内循环中重新加载BC
,方法是将LD BC,0x168
移至D32B。