Как последовательно читать элементы из DEFB на языке ассемблера Z80, а затем использовать значение, полученное на каждой итерации

Я изучал ассемблер Z80 и немного озадачен этим. Значения в DEFB представляют собой музыкальные высоты. Программа создает последовательный цикл, используя регистр A, начиная с 0, и должна прочитать n- й элемент DEFB, передать значение в регистр HL, а затем подать звуковой сигнал. Я не могу понять, как удалить жесткое кодирование и заставить это работать:

      ORG 30000

_MAIN
    LD A, 0         ;Set A to zero

LOOP_POINT:

    LD B, A         ;Load the current value of A into B to loop on
    CP 31           ;Check if the B value is 31
    JP Z, FINISHED      ;If yes, 32 notes have been played, so jump to FINISHED

    PUSH AF         ;Put current A value on the stack, because the "CALL 949" is going to overwrite it

    ;LD HL, (SOUND_BUFFER + A) - THIS DOES NOT WORK, I AM FORCED TO HARD CODE TO 855 FOR THIS EXAMPLE (BELOW)
    LD HL, 855      ;Load the pitch into HL
    LD DE, 24       ;Load the duration  into DE

    CALL 949        ;Will play the pitch in HL for the duration in DE

    POP AF          ;Restore the A value back from the stack

    INC A           ;Add 1

    CALL LOOP_POINT     

FINISHED:
    RET

SOUND_BUFFER                ;32 elements (each is a 1/4 note, so, 4*8 bars = 32 in total)

    DEFB "855,0,0,0,855,855,855,759,759,673,673,673,673,673,673,673,0,0,0,0,855,855,855,759,759,673,673,759,759,855,0,855"

Может ли кто-нибудь помочь мне с синтаксисом или указать правильное направление, пожалуйста?

1 ответ

Вам нужно либо вычислить указатель по индексу в A, либо просто сохранить указатель и обновлять его по мере прохождения массива. Ниже мой вариант (на основе вашего исходного кода) – не проверен, никаких гарантий. Также обратите внимание, что я изменил ваш DEFB на DEFW — я не знаком с вашей версией ассемблера, поэтому это может быть неправильно, но поскольку шаг представлен 16-битными значениями, я ожидаю, что DEFW (или DW) будет использовал.

РЕДАКТИРОВАТЬ: И, учитывая способ кодирования, вам нужно сравнивать A с 32, а не с 31. В противном случае последняя нота не воспроизводится.

Надеюсь это поможет.

        ORG 30000

_MAIN
  LD A, 0         ;Set A to zero
  LD HL,SOUND_BUFFER  ;Store pointer in HL

LOOP_POINT:

  ;;;LD B, A         ;Load the current value of A into B to loop on
  CP 32           ;Check if the A value is 32
  JP Z, FINISHED      ;If yes, 32 notes have been played, so jump to FINISHED

  PUSH AF         ;Put current A value on the stack, because the "CALL 949" is going to overwrite it

  ;;;LD HL, 855      ;Load the pitch into HL
  LD E, (HL)      ;Load least significant byte into E
  INC HL          ;Bump pointer
  LD D,(HL)       ;Load most significant byte into D, DE contains the pitch 
  INC HL          ;Bump pointer
  PUSH HL         ;Save HL (pointing to next pitch)
  EX DE,HL        ;Move pitch from DE to HL
  LD DE, 24       ;Load the duration into DE

  CALL 949        ;Will play the pitch in HL for the duration in DE

  POP HL          ;Restore HL (pointing to next pitch)
  POP AF          ;Restore the A value back from the stack

  INC A           ;Add 1

  ;;;CALL LOOP_POINT     ; why CALL?
  JR LOOP_POINT   ; just jump

 FINISHED:
  RET

SOUND_BUFFER                ;32 elements (each is a 1/4 note, so, 4*8 bars = 32 in total)
  DEFW 855,0,0,0,855,855,855,759,759,673,673,673,673,673,673,673,0,0,0,0,855,855,855,759,759,673,673,759,759,855,0,855
Другие вопросы по тегам