在 6502 上使用零页间接寻址循环访问内存
Looping through memory using Zero Page indirect addressing on the 6502
我编写了一个 6502 小程序来遍历内存并使用 STA 零页间接寻址将值存储在 128 个连续的内存位置,但该程序似乎无法运行。它应该将值 $01 的 128 个副本存储到内存地址 $0400 之后,但它没有。我做错了什么?
*=01
; set [=10=], to 00
LDA #[=10=]
STA [=10=]
LDA #
STA
CLC ; Clear carry and decimal mode
CLD
LDX #128 ; Loop 128 times
LDY #0
loop LDA # ; the value to store
STA ([=10=]),Y ; store A to the address held in [=10=],
; Add 1 to [=10=], (16-bit addition)
LDA [=10=]
ADC #1
STA [=10=]
LDA
ADC #0
STA
; do it 127 more times
DEX
BNE loop
RTS
看起来您正在递增 [=16=]
中存储的值,但您不应该改为操纵 Y
吗?类似于:
*=01
LDA #<00 ; store 00 into [=10=] and
STA [=10=]
LDA #>00
STA
LDY #128 ; load 128 into Y
LDA # ; load 01 into A
loop DEY
STA ([=10=]),Y ; store A into 00 + Y
BNE loop ; loop until Y is zero
RTS
在这个循环中,我们去掉X
,将Y
初始化为128,然后在每次循环迭代中递减Y
。这意味着我们正在“向后”填充内存。
备注 1
地址 [=16=]
和 </code> 通常很特殊(例如,
在 C64 上,这些地址控制处理器功能),因此取决于
在您的环境中,您可能需要选择不同的零内存
地点。</p>
<h2>注2</h2>
<p>如果我写这个,我会避免将地址直接硬编码到代码中,而是声明一个命名的存储位置。在本地测试您的代码时,我使用 <a href="http://tass64.sourceforge.net/" rel="nofollow noreferrer">64tass</a> 和以下代码组装它:</p>
<pre><code> *=[=11=]fb
addr .word ? ; declare two bytes of storage at * and *+1
; I'm using [=11=]fb because this is an unused zero
; page location on the c64 (and I'm testing using
; the VICE emulator).
*=01
LDA #<00 ; store 00 into addr and addr+1
STA addr
LDA #>00
STA addr+1
LDY #128
LDA #
loop DEY
STA (addr),Y
BNE loop
RTS
更新 1
你的原始代码对我来说似乎工作得很好。请注意,在 C64 仿真器中进行测试时,范围 00-80
对应于屏幕内存(参见 this memory map),因此当 return 转换为 BASIC 时,该范围将被覆盖。例如,当您的代码加载到 01
时,我在监视器中看到以下代码(假设我们将地址存储在 $FB
和 $FC
中):
(C:$e5cf) d 8001
.C:8001 A9 00 LDA #[=12=]
.C:8003 85 FB STA $FB
.C:8005 A9 04 LDA #
.C:8007 85 FC STA $FC
.C:8009 18 CLC
.C:800a D8 CLD
.C:800b A2 80 LDX #
.C:800d A0 00 LDY #[=12=]
.C:800f A9 01 LDA #
.C:8011 91 FB STA ($FB),Y
.C:8013 A5 FB LDA $FB
.C:8015 69 01 ADC #
.C:8017 85 FB STA $FB
.C:8019 A5 FC LDA $FC
.C:801b 69 00 ADC #[=12=]
.C:801d 85 FC STA $FC
.C:801f CA DEX
.C:8020 D0 ED BNE 0F
.C:8022 60 RTS
如果我在 22
处放置断点并调整代码...
(C:29) break 8022
BREAK: 1 C:22 (Stop on exec)
(C:29) g 8001
#1 (Stop on exec 8022) 064 011
.C:8022 60 RTS - A:04 X:00 Y:00 SP:f2 ..-...Z. 4131803
然后检查目标内存范围,里面填满了</code>:</p>
<pre><code>(C:22) m 400,480
>C:0400 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0420 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0430 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0440 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0450 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0460 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0470 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0480 20
但是一旦我 return 到 BASIC,它看起来像这样:
(C:$e5d4) m 400,480
>C:0400 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0410 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0420 20 20 20 20 20 20 20 20 12 05 01 04 19 2e 20 20 ......
>C:0430 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0440 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0450 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0460 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0470 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0480 20
我编写了一个 6502 小程序来遍历内存并使用 STA 零页间接寻址将值存储在 128 个连续的内存位置,但该程序似乎无法运行。它应该将值 $01 的 128 个副本存储到内存地址 $0400 之后,但它没有。我做错了什么?
*=01
; set [=10=], to 00
LDA #[=10=]
STA [=10=]
LDA #
STA
CLC ; Clear carry and decimal mode
CLD
LDX #128 ; Loop 128 times
LDY #0
loop LDA # ; the value to store
STA ([=10=]),Y ; store A to the address held in [=10=],
; Add 1 to [=10=], (16-bit addition)
LDA [=10=]
ADC #1
STA [=10=]
LDA
ADC #0
STA
; do it 127 more times
DEX
BNE loop
RTS
看起来您正在递增 [=16=]
中存储的值,但您不应该改为操纵 Y
吗?类似于:
*=01
LDA #<00 ; store 00 into [=10=] and
STA [=10=]
LDA #>00
STA
LDY #128 ; load 128 into Y
LDA # ; load 01 into A
loop DEY
STA ([=10=]),Y ; store A into 00 + Y
BNE loop ; loop until Y is zero
RTS
在这个循环中,我们去掉X
,将Y
初始化为128,然后在每次循环迭代中递减Y
。这意味着我们正在“向后”填充内存。
备注 1
地址 [=16=]
和 </code> 通常很特殊(例如,
在 C64 上,这些地址控制处理器功能),因此取决于
在您的环境中,您可能需要选择不同的零内存
地点。</p>
<h2>注2</h2>
<p>如果我写这个,我会避免将地址直接硬编码到代码中,而是声明一个命名的存储位置。在本地测试您的代码时,我使用 <a href="http://tass64.sourceforge.net/" rel="nofollow noreferrer">64tass</a> 和以下代码组装它:</p>
<pre><code> *=[=11=]fb
addr .word ? ; declare two bytes of storage at * and *+1
; I'm using [=11=]fb because this is an unused zero
; page location on the c64 (and I'm testing using
; the VICE emulator).
*=01
LDA #<00 ; store 00 into addr and addr+1
STA addr
LDA #>00
STA addr+1
LDY #128
LDA #
loop DEY
STA (addr),Y
BNE loop
RTS
更新 1
你的原始代码对我来说似乎工作得很好。请注意,在 C64 仿真器中进行测试时,范围 00-80
对应于屏幕内存(参见 this memory map),因此当 return 转换为 BASIC 时,该范围将被覆盖。例如,当您的代码加载到 01
时,我在监视器中看到以下代码(假设我们将地址存储在 $FB
和 $FC
中):
(C:$e5cf) d 8001
.C:8001 A9 00 LDA #[=12=]
.C:8003 85 FB STA $FB
.C:8005 A9 04 LDA #
.C:8007 85 FC STA $FC
.C:8009 18 CLC
.C:800a D8 CLD
.C:800b A2 80 LDX #
.C:800d A0 00 LDY #[=12=]
.C:800f A9 01 LDA #
.C:8011 91 FB STA ($FB),Y
.C:8013 A5 FB LDA $FB
.C:8015 69 01 ADC #
.C:8017 85 FB STA $FB
.C:8019 A5 FC LDA $FC
.C:801b 69 00 ADC #[=12=]
.C:801d 85 FC STA $FC
.C:801f CA DEX
.C:8020 D0 ED BNE 0F
.C:8022 60 RTS
如果我在 22
处放置断点并调整代码...
(C:29) break 8022
BREAK: 1 C:22 (Stop on exec)
(C:29) g 8001
#1 (Stop on exec 8022) 064 011
.C:8022 60 RTS - A:04 X:00 Y:00 SP:f2 ..-...Z. 4131803
然后检查目标内存范围,里面填满了</code>:</p>
<pre><code>(C:22) m 400,480
>C:0400 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0420 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0430 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0440 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0450 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0460 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0470 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0480 20
但是一旦我 return 到 BASIC,它看起来像这样:
(C:$e5d4) m 400,480
>C:0400 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0410 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0420 20 20 20 20 20 20 20 20 12 05 01 04 19 2e 20 20 ......
>C:0430 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0440 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0450 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0460 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0470 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0480 20