Читайте в памяти и вкл. (6502)
Извините, если вопрос кажется "слишком базовым". Я кодер 68K ASM, но один из друзей попросил меня взглянуть на код 6502. У нас есть указатель на строку данных:
my_ptr ds 2
Этот указатель устанавливается с помощью этого кода:
ldx sound_channel_busy
bne .abc_set_score1 ; at bottom of code
sta my_ptr ; fill the pointer
Чтение данных сделано с
lda (my_ptr),y ; my_ptr + offset
Но, как я вижу в документе 6502, у - один байт. Таким образом, при этом невозможно использовать строку данных длиной более 255 байт, что не достаточно (мы хотим прочитать строки размером 10.000 байт или более. Я предлагаю, чтобы мой друг сделал это:
1) Установите один указатель как "базовый" и временный, который мы включим при чтении
my_ptr ds 2
my_ptr_tmp ds 2
2) Инициируйте их с помощью:
ldx sound_channel_busy
bne .abc_set_score1
sta my_ptr
sta my_ptr_tmp ; Duplicate
3) Затем прочитайте, используя:
lda (my_ptr_tmp) ; Read to acumulator
inc my_ptr_tmp ; One more on adress pointer
Но это не работает, так как мой друг - разработчик C, и у нас нет отладчика... не легко. В 68К это кажется логичным, но в 6502?
Большое спасибо за вашу помощь
2 ответа
6502 довольно ограничен.
- Все чтения и записи в память 8 бит
- Вся арифметика 8 бит
Есть только два косвенных режима:
(zp),y
а также(zp,x)
whererzp
это адрес нулевой страницы. Первый рассчитывает адрес какcontentOf(zp + (zp + 1) << 8) + y
и использует байт в качестве операнда. Последний рассчитывает адрес как
contentOf( zp + x + (zp + x + 1) << 8)
Форма y используется для доступа к элементам массивов, на которые указывает указатель нулевой страницы, а форма x используется для доступа к таблицам векторов в памяти нулевой страницы.
Чтобы установить указатель:
lda #<pointer ; The low byte of the 16 bit address pointer is loaded into A
sta my_ptr
lda #>pointer ; the high byte of the pointer
sta my_ptr+1
ldy #0 ; zero the y register
Для доступа к указателю
loopStart:
lda (my_ptr),y
Предполагая строку в стиле C с нулевым терминатором
beq loopExit ; previous LDA sets the S and Z flags.
Увеличить указатель
iny ; Increment y
bne loopStart
inc my_ptr+1
jmp loopStart
Вы также можете сделать это, сохранив Y равным 0 и увеличивая младший байт и две позиции нулевой страницы, но INC my_ptr
намного медленнее, чем INY
принимая пять циклов вместо двух.
редактировать
Если вместо строки с нулевым символом в конце у вас есть длина, вам нужно немного ее изменить. Один из способов - подсчитать, сколько байтов вы сделали, и сравнить с длиной. В приведенном выше алгоритме Y - это счетчик, если длина < 256, поэтому мы можем сохранить старший байт счетчика в
; first set up my_ptr, same as before.
;
lda #<pointer ; The low byte of the 16 bit address pointer is loaded into A
sta my_ptr
lda #>pointer ; the high byte of the pointer
sta my_ptr+1
;
; Set up the counter
;
ldx #0 ; set up x for the count
ldy #0 ; Set up y for the count/loop
;
; A common trick with compiling while loops is to put the test at the end of the loop and jump to it immediately.
; This means you don't have to reverse the logic of the loop condition.
;
jmp loopTest ; Omit this if you definitely need to go round the loop at least once
loopStart:
lda (my_ptr),y ; Get the byte
;
; Do what you need to do here
;
; Increment the counter
;
iny ; Increment y
bne loopTest
inx
inc my_ptr+1
loopTest:
cpy length ; Compare the low byte of length to the count
bne loopStart
cpx length+1 ; Compare the high byte of length to the count
bne loopStart
6502 - это 8-битные данные, 16-битный адрес, поэтому ваши указатели должны быть 2 байта, обычно на нулевой странице.
lda #<addr ;low byte
sta my_ptr
sta my_ptr_tmp
lda #>addr ;high byte
sta my_ptr+1
sta my_ptr_tmp+1
Inc также должен быть 16-битным:
inc my_ptr_tmp
bne :skip
inc my_ptr_tmp+1 ;only inc high byte if low byte is zero
:skip
Также обратите внимание, что lda (zp) без X или Y доступна только на 65C02.