Читайте в памяти и вкл. (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) wherer zp это адрес нулевой страницы. Первый рассчитывает адрес как

    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.

Другие вопросы по тегам