Как последовательно читать элементы из 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