Модифицированный возврат прерываний 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

Это намного меньше накладных расходов, чем установка флага и ветвление на основе этого флага. Предположительно, ваша цель — как можно быстрее обновить цвет рамки/фона, и это значительно сократит время, затрачиваемое на проверку условий.

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