我现在开始使用6502装配,并且在绕过需要处理大于8位的数字的循环时遇到问题.
具体来说,我想循环一些内存位置.在伪c代码中,我想这样做:
// Address is a pointer to memory
int* address = 0x44AD;
for(x = 0; x < 21; x++){
// Move pointer forward 40 bytes
address += 0x28;
// Set memory location to 0x01
&address = 0x01;
}
Run Code Online (Sandbox Code Playgroud)
所以从地址开始$44AD我想写入$01ram,然后向前跳$28,写入$01,然后再向前跳$28,直到我完成了20次(写的最后一个地址是$47A5).
我目前的方法是循环展开,编写起来很繁琐(尽管我认为汇编程序可以更简单):
ldy #$01
// Start from $44AD for the first row,
// then increase by $28 (40 dec) for the next 20
sty $44AD
sty $44D5
sty $44FD
[...snipped..]
sty $477D
sty $47A5
Run Code Online (Sandbox Code Playgroud)
我知道绝对寻址(使用累加器而不是Y寄存器 - sta $44AD, x),但这只给我一个0到255之间的数字.我真正想要的是这样的:
lda #$01
ldx #$14 // 20 Dec
loop: sta $44AD, x * $28
dex
bne loop
Run Code Online (Sandbox Code Playgroud)
基本上,从最高地址开始,然后循环.问题是$ 14*$ 28 = $ 320或800 dec,这比我实际存储在8-bit X寄存器中的要多.
有一种优雅的方式来做到这一点?
6502是一个8位处理器,因此您无法完全在寄存器中计算16位地址.您将需要间接通过第0页.
// set $00,$01 to $44AD + 20 * $28 = $47CD
LDA #$CD
STA $00
LDA #$47
STA $01
LDX #20 // Loop 20 times
LDY #0
loop: LDA #$01 // the value to store
STA ($00),Y // store A to the address held in $00,$01
// subtract $28 from $00,$01 (16-bit subtraction)
SEC
LDA $00
SBC #$28
STA $00
LDA $01
SBC #0
STA $01
// do it 19 more times
DEX
BNE loop
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用自修改代码.这是一种可疑的技术,但在6502等嵌入式处理器上很常见,因为它们非常有限.
// set the instruction at "patch" to "STA $47CD"
LDA #$CD
STA patch+1
LDA #$47
STA patch+2
LDX #20 // Loop 20 times
loop: LDA #$01 // the value to store
patch:STA $FFFF
// subtract $28 from the address in "patch"
SEC
LDA patch+1
SBC #$28
STA patch+1
LDA patch+2
SBC #0
STA patch+2
// do it 19 more times
DEX
BNE loop
Run Code Online (Sandbox Code Playgroud)