Я пытаюсь изучить логику мнемоники и попробовал этот простой тест на C64 asm, сделанный с помощью VSCode и Kick Asm. По сути, я пытаюсь напечатать символы последовательности в верхнем левом углу от 0 до 9, а затем наоборот. Это рабочая попытка:
.label SCREEN_RAM = $0400 // Start of C64 screen memory
// --- Variable ---
counter: .byte 0
//backCounter: .byte 39
animationDirection: .byte 1 // Start animation going forward (0=backward, 1=forward)
.var backCounter = $39
BasicUpstart2(main)
main:
lda #0 // Initialize a counter to 0
sta counter
jmp checkloop
checkloop:
ldy animationDirection // Load the current direction flag
cpy #1
beq print_loop_forward
//.break
//lda #10 // Load the desired value into the accumulator
//sta counter // Store the value from the accumulator into 'counter'
ldy #backCounter //#$39
jsr print_loop_backwards
jmp exit2
print_loop_backwards:
//.break
//ldy #backCounter //#$39 no!
ldx counter // Load the counter into Y register (for offsetting)
tya
sta SCREEN_RAM, x // Store the character on the screen with offset
dey
inc counter
ldx counter
cpx #20
bne print_loop_backwards // Compare with 10 (decimal)
rts
print_loop_backwards_not_working:
.break
lda #backCounter //#$39
ldx counter // Load the counter into Y register (for offsetting)
sta SCREEN_RAM, x // Store the character on the screen with offset
dec backCounter
//.break
inc counter
ldx counter
cpx #20
bne print_loop_backwards // Compare with 10 (decimal)
rts
print_loop_forward:
//.break
lda counter // Load the counter value into the accumulator
//cmp #0
//beq exit
clc
adC#$30 // Add $30 to convert to ASCII
ldx counter // Load the counter into Y register (for offsetting)
sta SCREEN_RAM, x // Store the character on the screen with offset
inc counter
ldx counter
cpx #10
bne print_loop_forward // Compare with 10 (decimal)
//.break
lda #0
sta animationDirection
jmp checkloop
exit: // Label for the exit point
rts
exit2: // Label for the exit point
lda #$21 // Load the counter into Y register (for offsetting)
ldx #$99
sta $0500, x
rts
Как вы можете видеть, я попробовал другой способ сделать это в этом цикле:
print_loop_backwards_not_working
Сначала я попробовал эту попытку, безуспешно изменив переменную «backCounter» во время цикла, но не понял, почему переменная не отражает такие изменения, как «счетчик», который я могу изменить с помощью INC. Пробовал с помощью DEC, как вы видите, но также и с SEC\SBC#$1.
Очевидно, хотя безуспешно пробовал этот метод, строка:
ldy #backCounter //#$39
был закомментирован.
Надеюсь, кто-нибудь поможет мне прояснить это!
Коды операций 6502/6510 имеют немедленный, абсолютный и косвенный режимы. Если вы хотите использовать адрес памяти в качестве счетчика, вам следует использовать абсолютный режим, который можно представить, как показано ниже.
LDA $FFFF
или это версия Zeropage;
LDA $FF
Вы пытаетесь использовать немедленный режим, который выглядит следующим образом:
LDA #$FF
Итак, у вас есть три разумных варианта.
1 – Используйте абсолютный режим, как показано ниже;
LDY backCounter
...
DEC backCounter
Абсолютный режим считывает backCounter из адреса памяти в регистр Y, и когда нам нужно уменьшить счетчик, мы непосредственно уменьшаем память. Когда мы прочитаем адрес памяти в следующий раз, он уже уменьшится.
2 – Используйте модифицирующий код. Я не рекомендую это, я делюсь этим как альтернативный вариант.
label1:
LDY #backCounter
...
DEC label1+1
Здесь мы используем немедленный режим и уменьшаем параметр кода операции в памяти. Не забывайте, что если вы не сбросите параметр, ваш код в следующий раз не будет работать с начальным значением backCounter.
3. Используйте регистры напрямую. Это самый быстрый метод, который вы уже используете в своем рабочем примере.
LDY #backCounter
...
DEY
Пока у вас есть бесплатные регистры, вам следует использовать регистры. Если у вас закончились регистры, используйте абсолютный режим, например «LDY backCounter», — ваш второй лучший вариант. Самомодифицирующийся код время от времени может быть очень полезен. Но это не самый безопасный вариант и может вызвать некоторые побочные эффекты. В современных процессорах самомодифицирующийся код может быть ограничен или, по крайней мере, вызывать проблемы с кэшированием и значительно замедлять работу вашего кода. Но в старую добрую эпоху 8-битных процессоров самомодифицирующийся код можно было безопасно использовать, если вы знали, что делаете.
lda #backCounter
помещает адресbackCounter
в аккумулятор (ну, младший байт адреса, поскольку это все, что помещается). Это постоянное значение, на которое не повлияет увеличение или уменьшениеbackCounter
.