Модифицированный возврат прерываний 6502
Я пытаюсь переключить нормальный поток программы, пока прерывание возвращается:
START
SEI
LDX #<IRQ
LDY #>IRQ
STX $FFFE
STY $FFFF
CLI
LOOP1
INC $D020
JMP LOOP1
LOOP2
INC $D021
JMP LOOP2
IRQ
STA SAVEA+1
STX SAVEX+1
STY SAVEY+1
// Some Routines
LDA #$00
PHA
LDA #<LOOP2
PHA
LDA #>LOOP2
PHA
SAVEA
LDA #$00
SAVEX
LDX #$00
SAVEY
LDY #$00
RTI
Я написал этот код в соответствии с этим источником: http://6502.org/tutorials/interrupts.html
Но причина сбоя PHA, как переключить нормальный поток LOOP1 на LOOP2 при прерывании?
3 ответа
Простой способ это:
TSX
LDA #$00
STA $0101,X // Processor Status
LDA #<LOOP2
STA $0102,X // Task Low Address
LDA #>LOOP2
STA $0103,X // Task High Address
Но для более сложного управления задачами нам нужно сохранить регистры A,X,Y для каждой задачи:
START
SEI
LDX #<IRQ
LDY #>IRQ
STX $FFFE
STY $FFFF
CLI
LOOP1
INC $D020
JMP LOOP1
LOOP2
INC $D021
JMP LOOP2
IRQ
STA $FF
STX $FE
STY $FD
LDX TASK+1
CPX TASK
BEQ CONT
LDY TASKI,X
TSX
LDA $0101,X
STA TASKS+0,Y
LDA $0102,X
STA TASKS+1,Y
LDA $0103,X
STA TASKS+2,Y
LDA $FF
STA TASKS+3,Y
LDA $FE
STA TASKS+4,Y
LDA $FD
STA TASKS+5,Y
LDA TASK
STA TASK+1
CONT
// Change Task
LDA TASK
CLC
ADC #$01
AND #$01
STA TASK
LDX TASK
CPX TASK+1
BEQ CONT2
STX TASK+1
LDY TASKI,X
TSX
LDA TASKS+0,Y
STA $0101,X
LDA TASKS+1,Y
STA $0102,X
LDA TASKS+2,Y
STA $0103,X
LDA TASKS+3,Y
STA $FF
LDA TASKS+4,Y
STA $FE
LDA TASKS+5,Y
STA $FD
CONT2
LDA $FF
LDX $FE
LDY $FD
RTI
TASK
.BYTE 0,0
TASKI
.BYTE 0,6,12,18,24,30,36
TASKS
.BYTE 0,<LOOP1,>LOOP1,0,0,0
.BYTE 0,<LOOP2,>LOOP2,0,0,0
Самое простое, вероятно, иметь две области стека - по одной для каждой задачи. Например, 100-17 долларов и 180-1 долларов. Тогда у вас будет код переключения задачи прерывания, подобный следующему:
pha
txa
pha
tya
pha ;saving task's registers on its stack,
;where flags and PC are already saved
;by entering the interrupt
tsx
stx ... ;save task's stack position
... ;select new task to run/etc.
ldx ...
txs ;load other task's stack position
pla
tay
pla
tax
pla ;restore other task's registers
rti ;and finally continue other task
Я не совсем уверен, что вы пытаетесь сделать, но мне кажется, что вы хотите быстро изменить цвета фона на Commodore 64. Если вы хотите изменить то, что вы делаете, на самом деле есть гораздо более простой способ:
START
SEI
LDX #<IRQ
LDY #>IRQ
STX $FFFE
STY $FFFF
CLI
LOOP1
INC $D020 ;the interrupt will switch this to $D021 and back every time it happens.
JMP LOOP1
IRQ
PHA
LDA #$01
EOR LOOP1+1 ;the value at this address is the "20" in "INC $D020"
STA LOOP1+1 ;toggle between "INC $D020" and "INC $D021" each IRQ
PLA
RTI
Это намного меньше накладных расходов, чем установка флага и ветвление на основе этого флага. Предположительно, ваша цель — как можно быстрее обновить цвет рамки/фона, и это значительно сократит время, затрачиваемое на проверку условий.